Skip to content

Instantly share code, notes, and snippets.

@antonjb
Last active May 31, 2020 12:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save antonjb/b5646512a7c20fc70840345445b18fc8 to your computer and use it in GitHub Desktop.
Save antonjb/b5646512a7c20fc70840345445b18fc8 to your computer and use it in GitHub Desktop.
Generated by XState Viz: https://xstate.js.org/viz
// Idle
// after 30 seconds check status
// if in timezone && status promise resolves
// state => live
// live State
// after 30 seconds check status
// substate state == stop && outside timezone => state: idle
// substate state == play && fetch response reject => state: closing
// neither conditions pass => no op. check again in 30 seconds
// substates
// stop
// user interaction => load
// load
// load stream => play
// playing
// user interaction => stop
// Live state exists with substates because interface changes when
// things are live. Doesn't matter what player is doing but UI will
// react
// Idle
// after 30 seconds check status
// if in timezone && status promise resolves
// state => live
// live State
// after 30 seconds check status
// substate state == stop && outside timezone => state: idle
// substate state == play && fetch response reject => state: closing
// neither conditions pass => no op. check again in 30 seconds
// substates
// stop
// user interaction => load
// load
// load stream => play
// playing
// user interaction => stop
// Live state exists with substates because interface changes when
// things are live. Doesn't matter what player is doing but UI will
// react
const pollTimer = 3000
const streamMachine = Machine({
id: 'streamMachine',
initial: 'idle',
context: {
hostname: null,
failures: 0,
},
invoke: [
{
src: "checkStatus"
},
],
states: {
idle: {
after: {
DELAY_TIMER: 'scheduleCheck'
}
},
scheduleCheck: {
entry: [send("CHECK", { to: 'checkStatus'})],
on: {
'STATUS.IDLE': 'idle',
'STATUS.LIVE': 'live',
}
},
live: {
onEntry: ['setHostname'],
initial: 'stopped',
states: {
stopped: {
invoke: {
id: 'stopPoll',
src: 'poll'
},
entry: [() => console.log('stopped entered')],
on: {
LOAD: 'loading',
'STATUS.IDLE': '#streamMachine.idle',
POLL: {actions: ['pollStatusTimeResponse']}
}
},
loading: {
on: {
LOADED: 'playing',
}
},
playing: {
invoke: {
id: 'playPoll',
src: 'poll',
},
entry: [() => console.log('playing entered')],
on: {
STOP: 'stopped',
POLL: {actions: ['pollStatusResponse']},
'STATUS.IDLE': 'closing'
}
},
closing: {
after: {
DELAY_TIMER: '#streamMachine.idle'
}
}
}
},
}
}, {
delays: {
DELAY_TIMER: pollTimer,
},
actions: {
setHostname: assign({ hostname: (_ctx, evt) => evt.hostname }),
pollStatusTimeResponse: send('CHECK', { to: 'checkStatus' }),
pollStatusResponse: send('CHECK.RESPONSE', { to: 'checkStatus' })
},
services: {
poll: () => (cb) => {
const intervalId = setInterval(() => cb('POLL'), pollTimer);
return () => clearInterval(intervalId)
},
checkStatus: () => (cb, receive) => {
receive(async (e) => {
if (e.type === 'CHECK') {
if (Math.random() < 0.3) {
console.log('status check: within time schedule')
return cb('STATUS.IDLE')
}
}
const result = await (new Promise((resolve, reject) => {
console.log('status check: live')
if (Math.random() > 0.2) {
resolve({ source: { type: 'live' }, hostname: 'test.com' })
} else {
resolve({ source: {
type: 'automated'
} })
}
}))
if (result.source.type === 'live') {
console.log('status response: live')
return cb({type: 'STATUS.LIVE', hostname: result.hostname})
}
console.log('status response: automated')
cb('STATUS.IDLE')
})
}
},
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment