Skip to content

Commit

Permalink
feat: edge connect icon in the top app bar
Browse files Browse the repository at this point in the history
- Fix end of newsfeed detection
- other cosmetic fixes
- improved handling of corrupted connection
- connection reset after a long period of unsuccessful connection attempt
  • Loading branch information
ivelin committed Feb 20, 2020
1 parent 93a1e84 commit ee4afd0
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 35 deletions.
35 changes: 28 additions & 7 deletions src/components/AppFrame.vue
Original file line number Diff line number Diff line change
Expand Up @@ -101,10 +101,18 @@
class="hidden-sm-and-down"
/>
<v-spacer />
<v-btn icon>
<v-icon>mdi-apps</v-icon>
<v-btn
icon
v-if="!isEdgeConnected"
@click="$router.push('edge-connect')"
>
<v-icon>
mdi-download-off
</v-icon>
</v-btn>
<v-btn icon>
<v-btn
icon
>
<v-badge
top
right
Expand All @@ -113,7 +121,7 @@
class="align-self-center"
:content="newFavorites"
:value="newFavorites"
show=false
show="false"
>
<v-icon>mdi-heart</v-icon>
</v-badge>
Expand All @@ -133,15 +141,14 @@
</v-btn>
<v-btn
icon
large
>
<v-avatar
size="32px"
item
>
<v-img
src="@/assets/logo5.svg"
alt="Vuetify"
alt="Ambianic.ai logo"
/>
</v-avatar>
</v-btn>
Expand All @@ -166,6 +173,11 @@
</template>

<script>
import { mapState } from 'vuex'
import {
PEER_CONNECTED
} from '@/store/mutation-types'

export default {
name: 'AppFrame',
components: {
Expand All @@ -177,6 +189,7 @@ export default {
drawer: null,
newFavorites: 0,
newAlerts: 2,
on: true,
items: [
{ icon: 'history', text: 'Timeline', link: '/timeline' },
// { icon: 'mdi-account-heart-outline', text: 'People', link: '/people' },
Expand Down Expand Up @@ -210,6 +223,14 @@ export default {
{ icon: 'help', text: 'Help', link: '/help' },
{ icon: 'info', text: 'About Ambianic', link: '/about' }
]
})
}),
computed: {
...mapState({
isEdgeConnected: function (state) {
console.debug(`app frame: state.pnp.peerConnectionStatus: ${state.pnp.peerConnectionStatus}`)
return state.pnp.peerConnectionStatus === PEER_CONNECTED
}
})
}
}
</script>
6 changes: 3 additions & 3 deletions src/remote/peer-fetch.js
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ export class PeerFetch {
}
// get a ticket that matches the request
// and use it to claim the corresponding
// response when availably
// response when available
const ticket = this._enqueueRequest(request)
const response = await this._receiveResponse(ticket)
return response
Expand Down Expand Up @@ -236,7 +236,7 @@ export class PeerFetch {
setTimeout(() => this._processNextTicketInLine(), 50)
return response
} else {
console.debug('Waiting for response...', { ticket, request })
// console.debug('Waiting for response...', { ticket, request })
return null
}
}
Expand All @@ -250,7 +250,7 @@ export class PeerFetch {
response = this._checkResponseReady(ticket)
timeElapsed = Date.now() - timerStart
await sleep(200)
console.debug('Response time elapsed:', { ticket, timeElapsed })
// console.debug('Response time elapsed:', { ticket, timeElapsed })
} while (!response && timeElapsed < timeout)
if (!response) {
// check if response came in after the last sleep
Expand Down
81 changes: 60 additions & 21 deletions src/store/pnp.js
Original file line number Diff line number Diff line change
Expand Up @@ -174,63 +174,72 @@ function setPnPServiceConnectionHandlers (
commit(PNP_SERVICE_CONNECTED)
// Workaround for peer.reconnect deleting previous id
if (peer.id === null) {
console.log('pnpService: Received null id from peer open')
console.log('pnp client: Received null id from peer open')
peer.id = state.myPeerId
} else {
if (state.myPeerId !== peer.id) {
console.log(
'pnpService: Service returned new peerId. Old, New',
'pnp client: Service returned new peerId. Old, New',
state.myPeerId,
peer.id
)
commit(NEW_PEER_ID, peer.id)
}
}
console.log('pnpService: myPeerId: ', peer.id)
console.log('pnp client: myPeerId: ', peer.id)
// signaling server connection established
// we can advance to peer discovery
dispatch(PEER_DISCOVER)
})
peer.on('disconnected', function () {
commit(PNP_SERVICE_DISCONNECTED)
commit(USER_MESSAGE, 'PnP service connection lost. Please check your internet connection.')
console.log('pnpService: Connection lost. Please reconnect.')
console.log('pnp client: Connection lost. Please reconnect.')
})
peer.on('close', function () {
// peerConnection = null
commit(USER_MESSAGE, 'PnP service connection closed. Will attempt to reconnect in a moment.')
console.log('Connection to PnP server destroyed')
console.log('Reconnecting to PnP server...')
commit(PNP_SERVICE_DISCONNECTED)
commit(PEER_DISCONNECTED)
setTimeout(() => { // give the network a few moments to recover
dispatch(INITIALIZE_PNP)
}, 3000)
})
peer.on('error', function (err) {
console.log('peer connection error', err)
console.log('PnP service connection error', err)
commit(USER_MESSAGE,
`
Error while connecting. Will retry shortly. Is the Internet connection OK?
`)
commit(PEER_CONNECTION_ERROR)
console.log('peerConnection error', state.peerConnectionStatus)
console.log('Trying to reconnect to PnP server...')
commit(PNP_SERVICE_DISCONNECTED)
commit(PEER_DISCONNECTED)
console.log('pnp service connection error', { err })
console.log('Will try to reconnect to PnP server...')
// retry peer connection in a few seconds
setTimeout(() => { // give the network a few moments to recover
dispatch(INITIALIZE_PNP)
}, 3000)
})
// remote peer tries to initiate connection
peer.on('connection', function (peerConnection) {
console.log('remote peer trying to establish connection')
setPeerConnectionHandlers({ state, commit, dispatch }, peerConnection)
console.debug('#####>>>>> remote peer trying to establish connection')
setPeerConnectionHandlers({ state, commit, dispatch, peerConnection })
commit(PEER_CONNECTING)
})
}

function setPeerConnectionHandlers ({ state, commit, dispatch }, peerConnection) {
function setPeerConnectionHandlers ({
state,
commit,
dispatch,
peerConnection,
hungupConnectionResetTimer
}) {
// setup connection progress callbacks
peerConnection.on('open', function () {
clearTimeout(hungupConnectionResetTimer)
const peerFetch = new PeerFetch(peerConnection)
console.debug('Peer DataConnection is now open. Creating PeerFetch wrapper.')
commit(PEER_FETCH, peerFetch)
Expand All @@ -243,8 +252,10 @@ function setPeerConnectionHandlers ({ state, commit, dispatch }, peerConnection)
})

peerConnection.on('close', function () {
clearTimeout(hungupConnectionResetTimer)
commit(PEER_DISCONNECTED)
commit(USER_MESSAGE, 'Connection to remote peer closed')
console.debug('#########>>>>>>>>> p2p connection closed')
console.debug('Will try to open a new peer connection shortly.')
setTimeout( // give the network a few moments to recover
() => dispatch(PEER_DISCOVER),
Expand All @@ -253,8 +264,10 @@ function setPeerConnectionHandlers ({ state, commit, dispatch }, peerConnection)
})

peerConnection.on('error', function (err) {
clearTimeout(hungupConnectionResetTimer)
commit(PEER_CONNECTION_ERROR, err)
console.debug('Error from peer DataConnection.', err)
commit(USER_MESSAGE, 'Error in connection to remote peer.')
console.debug('######>>>>>>> p2p connection error', { err })
console.debug('Will try a new connection shortly.')
commit(PEER_DISCONNECTED)
setTimeout( // give the network a few moments to recover
Expand Down Expand Up @@ -282,18 +295,18 @@ const actions = {
// if connection to pnp service already open, then nothing to do
if (peer && peer.open) return
// Create own peer object with connection to shared PeerJS server
console.log('pnpService: creating peer')
console.log('pnp client: creating peer')
// If we already have an assigned peerId, we will reuse it forever.
// We expect that peerId is crypto secure. No need to replace.
// Unless the user explicitly requests a refresh.
console.log('pnpService: last saved myPeerId', state.myPeerId)
console.log('pnp client: last saved myPeerId', state.myPeerId)
peer = new Peer(state.myPeerId, {
host: ambianicConf.AMBIANIC_PNP_HOST,
port: ambianicConf.AMBIANIC_PNP_PORT,
secure: ambianicConf.AMBIANIC_PNP_SECURE,
debug: 3
})
console.log('pnpService: peer created')
console.log('pnp client: peer created')
setPnPServiceConnectionHandlers({ state, commit, dispatch }, peer)
commit(PNP_SERVICE_CONNECTING)
},
Expand All @@ -307,7 +320,7 @@ const actions = {
async [PNP_SERVICE_RECONNECT] ({ state, commit, dispatch }) {
// if connection to pnp service already open, then nothing to do
if (peer.open) return
console.log('pnpService: reconnecting peer...')
console.log('pnp client: reconnecting peer...')
// Workaround for peer.reconnect deleting previous id
if (!peer.id) {
console.log('BUG WORKAROUND: Peer lost ID. Resetting to last known ID.')
Expand All @@ -322,6 +335,7 @@ const actions = {
*
*/
async [PEER_DISCOVER] ({ state, commit, dispatch }) {
console.log(`######## >>>>> peerConnectionStatus = ${state.peerConnectionStatus}`)
if (state.peerConnectionStatus !== PEER_DISCONNECTED) {
// avoid redundant discovery loop
// in cases like multiple error events on the same connection
Expand Down Expand Up @@ -368,25 +382,50 @@ const actions = {
* direct peer-to-peer connection and data received on it.
*/
async [PEER_CONNECT] ({ state, commit, dispatch }, remotePeerId) {
// Its possible that the PNP signaling server connection was disrupted
// We need the signaling server to negotiate p2p connection terms.
if (state.pnpServiceConnectionStatus !== PNP_SERVICE_CONNECTED) {
console.log('PNP Service disconnected. Reconnecting...')
await dispatch(PNP_SERVICE_RECONNECT)
}
// if already connected to peer, then nothing to do
if (state.peerConnectionStatus === PEER_CONNECTING ||
state.peerConnectionStatus === PEER_CONNECTED) {
// avoid redundant connect looping
// in case of multiple connection errors
return
}
console.log('Connecting to remote peer', remotePeerId)
commit(PEER_CONNECTING)
console.log(`#####>>>> PNP Service connection status: ${state.pnpServiceConnectionStatus}`)
console.debug('#####>>>>>>> Connecting to remote peer', remotePeerId)
if (state.peerConnection) {
// make sure any previous connection is closed and cleaned up
console.warn('>>>>>>> Closing and cleaning up existing peer connection.')
console.info('>>>>>>> Closing and cleaning up existing peer connection.')
state.peerConnection.close()
}
console.warn('>>>>>> Opening new peer connection.')
console.info('>>>>>> Opening new peer connection.')
const peerConnection = peer.connect(remotePeerId, {
label: 'http-proxy', reliable: true, serialization: 'raw'
})
setPeerConnectionHandlers({ state, commit, dispatch }, peerConnection)
commit(PEER_CONNECTING)
// If we don't connect within a minute, there is a good chance
// the networking stack got corrupted. Let's reset it.
const hungupConnectionResetTimer = setTimeout(() => {
try {
peer.destroy()
} catch (err) {
console.warning('Error destroying peer.')
} finally {
console.info('It took too long to setup a connection. Resetting peer.')
dispatch(INITIALIZE_PNP)
}
}, 60 * 1000)
setPeerConnectionHandlers({
state,
commit,
dispatch,
peerConnection,
hungupConnectionResetTimer
})
},
/**
* Authenticate remote peer. Make sure its a genuine Ambianic Edge device.
Expand Down
2 changes: 1 addition & 1 deletion src/views/About.vue
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
>
<v-list-item-content>
<v-list-item-title class="headline">
News from Home
News from Your Home and Workspace
</v-list-item-title>
<v-list-item-subtitle>
via Ambient Intelligence
Expand Down
2 changes: 1 addition & 1 deletion src/views/Home.vue
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
>
<v-list-item-content>
<v-list-item-title class="headline">
News from Home
News from Your Home and Workspace
</v-list-item-title>
<v-list-item-subtitle>
via Ambient Intelligence
Expand Down
8 changes: 6 additions & 2 deletions src/views/Timeline.vue
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ export default {
const data = await this.getTimelineSlice()
console.debug('Infinite handler received timeline slice', { data }) // eslint-disable-line no-console
// Are there any more timeline events left?
if (data && data.timeline && data.timeline.length === PAGE_SIZE) {
if (data && data.timeline && data.timeline.length > 0) {
// eslint-disable-next-line
// console.debug('new timeline events: ', data.timeline.length)
// eslint-disable-next-line
Expand All @@ -337,10 +337,14 @@ export default {
)
this.timeline = this.timeline.concat(data.timeline)
$state.loaded()
if (this.timeline.length / PAGE_SIZE === 10) {
if (this.timeline.length / PAGE_SIZE === 10 ||
data.timeline.length < PAGE_SIZE) {
// 20 pages of timeline events is all we will show
// in the default view.
// More historical data can be found via search.
// Also if the result did not fill up a page
// then we are at the end of the current newsfeed.
// User can fefresh in a few moments or we can update automatically.
$state.complete()
}
} else {
Expand Down

0 comments on commit ee4afd0

Please sign in to comment.