Skip to content

Instantly share code, notes, and snippets.

@sarimarton
Last active November 28, 2019 10:58
Show Gist options
  • Save sarimarton/a6b332bdb3170d57f5c8b75b4321bf07 to your computer and use it in GitHub Desktop.
Save sarimarton/a6b332bdb3170d57f5c8b75b4321bf07 to your computer and use it in GitHub Desktop.
Auto-save SC
Auto-save SC
Idle*
change -> Saving
imagepaste -> Uploading
Uploading
goodresponse -> Saving
badresponse -> Idle
Saving&
Request
Request Start*
requeststarted -> Request Pending
Request Pending
goodresponse -> Request Success
badresponse -> Service Error
Request Success
Request Failed
Debounce
Debounce Start*
debouncestarted -> Debounce Active
Debounce Active
change -> Debounce Start
debounceover -> Debounce Ended
Debounce Ended
change -> Debounce Start
Dirtiness
Dirtiness Not Dirty*
change -> Dirtiness Dirty
Dirtiness Dirty
requestsuccess & debounceended & dirtinessnotdirty -> Idle
requestsuccess & debounceended & dirtinessdirty -> Saving
Service Error
Service Error Start
serviceerrorstarted -> Service Error Counting
Service Error Counting
serviceerrortick -> Service Error Counting
serviceerrorretry -> Service Error Retry
Service Error Retry
goodresponse -> Request Success
badresponse -> Service Error Counting
let debounceId
let revId = 0
let serviceAvailable = 1
let retryLevels = [10, 30, 5 * 60]
let retryLevel = 0
let counter = 0
let status = ''
let errorCounterId
function render(model) {
const states =
Object.entries(model.states)
.map(entry => entry[1])
.filter(s => s.is_active)
.map(s => s.name)
if (states.includes('Request Start')) {
revId += 1;
setTimeout(() => { model.emit(serviceAvailable ? 'goodresponse' : 'badresponse') }, 200)
model.emit('requeststarted')
}
if (states.includes('Request Success')) {
retryLevel = 0
}
if (states.includes('Request Failed')) {
counter = retryIntervals[retryLevel]
setTimeout(() => model.emit('retrytick'), 1000)
}
if (states.includes('Debounce Start')) {
clearTimeout(debounceId)
debounceId = setTimeout(() => model.emit('debounceover'), 500)
model.emit('debouncestarted')
}
// Transient transition - in SCXML:
// <transition cond="In('Request Completed') && In('Debounce Ended') && In('Dirtiness Not Dirty')" target="Idle" />
if (states.includes('Request Success') && states.includes('Debounce Ended') && states.includes('Dirtiness Not Dirty')) {
model.emit('requestsuccess & debounceended & dirtinessnotdirty')
}
// Transient transition - in SCXML:
// <transition cond="In('Request Completed') && In('Debounce Ended') && In('Dirtiness Dirty')" target="Saving" />
if (states.includes('Request Success') &&
states.includes('Debounce Ended') &&
states.includes('Dirtiness Dirty')
) {
model.emit('requestsuccess & debounceended & dirtinessdirty')
}
if (states.includes('Idle')) {
status = 'All changes are saved.'
}
if (states.includes('Saving')) {
status = 'Saving...'
}
if (states.includes('Service Error Start')) {
retryLevel = 0
counter = retryLevels[retryLevel]
model.emit('serviceerrorstarted')
}
if (states.includes('Service Error Counting')) {
status = <>
Server error, retrying in {counter}s...{' '}
<button onClick={() => {
counter = 0;
retryLevel = -1;
counter = retryLevels[retryLevel]
model.emit('serviceerrorretry')
}}>Retry now</button>
</>
if (counter > 0) {
clearTimeout(errorCounterId)
errorCounterId = setTimeout(() => {
counter -= 1
model.emit('serviceerrortick')
}, 1000)
} else {
model.emit('serviceerrorretry')
}
}
if (states.includes('Service Error Retry')) {
retryLevel = Math.min(retryLevel + 1, retryLevels.length - 1)
counter = retryLevels[retryLevel]
status = 'Retrying...'
setTimeout(() => { model.emit(serviceAvailable ? 'goodresponse' : 'badresponse') }, 200)
}
if (states.includes('Uploading')) {
setTimeout(() => {
model.emit('goodresponse')
}, 2000)
}
return (<pre>
Rev: {revId}<br />
Service {serviceAvailable ? 'OK'.padEnd(8) : 'Disabled'}{' '}
<button onClick={() => { serviceAvailable ^= 1; model.emit('') }}>{serviceAvailable ? 'Disable' : 'Enable'} Service</button>
{' '}
<button onClick={() => { model.emit('imagepaste') }}>Paste Image</button>
<br /><br />
{status}<br />
<textArea
disabled={states.includes('Uploading')}
onChange={() => model.emit('change')}
style={{ width: 465, height: 100, background: states.includes('Uploading') ? 'lightgray': 'transparent' }}
/>
</pre>)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment