Skip to content

Instantly share code, notes, and snippets.

@andrewiggins
Last active July 29, 2020 21:32
Show Gist options
  • Save andrewiggins/04c5a1e5a586bd75bb1e1aa946c89655 to your computer and use it in GitHub Desktop.
Save andrewiggins/04c5a1e5a586bd75bb1e1aa946c89655 to your computer and use it in GitHub Desktop.
Generated by XState Viz: https://xstate.js.org/viz
// Available variables:
// - Machine
// - interpret
// - assign
// - send
// - sendParent
// - spawn
// - raise
// - actions
// - XState (all XState exports)
const randomInt = (min, max) => Math.floor(Math.random() * (max - min)) + min;
const lockConfig = {
createDelayMs: 1000, // 1s
minHoldTimeMs: 2500, // 2.5s
checkDelayMs: 500, // 0.5s
minWaitTimeMs: 1000, // 1s
maxWaitTimeMs: 3000, // 3s
waitTimeoutMs: 60 * 1000, // 1 minute
};
const lockMachine = Machine(
{
id: "CommentLockMachine",
initial: "initialRead",
strict: true,
context: {
waitTime: 0,
totalWaitTime: 0,
totalHeldTime: 0,
},
states: {
initialRead: {
on: {
// comment doesn't exist
NOT_FOUND: "creating",
// comment exists, have hold
HELD: "holding",
// comment exists,
LOCKED: "acquiring",
},
},
creating: {
id: "creating",
initial: "waiting",
entry: "resetTotalWaitTime",
states: {
waiting: {
entry: "setWaitTime",
exit: "updateTotalWaitTime",
on: {
COMPLETE_WAIT: "searching",
},
},
searching: {
on: {
// comment doesn't exist, done waiting
CREATE: "creating",
// comment doesn't exist, need to wait
NOT_FOUND: "waiting",
// comment exists, try to acquire
LOCKED: "#acquiring",
// wait time exceeded time out
TIMEOUT: "#timed_out",
},
},
creating: {
on: {
ACQUIRED: "#acquired",
},
},
},
},
acquiring: {
id: "acquiring",
// We will only enter this state if the comment exists
// and it isn't ours so first wait
initial: "waiting",
entry: "resetTotalWaitTime",
states: {
// Wait random time before attempting to acquire again
waiting: {
entry: "setWaitTime",
exit: "updateTotalWaitTime",
on: {
COMPLETE_WAIT: "acquiring",
},
},
acquiring: {
on: {
HELD: "#holding",
// Comment exists, no one has lock
AVAILABLE: "writing",
// comment exists, is locked
LOCKED: "waiting",
// comment exists, wait timeout exceeded
TIMEOUT: "#timed_out",
},
},
writing: {
on: {
HELD: "#holding",
},
},
},
},
// Wait deterministic time before reading lock
holding: {
id: "holding",
initial: "holding",
context: {
totalHeldTime: 0,
},
entry: "resetTotalHeldTime",
states: {
holding: {
exit: "updateTotalHeldTime",
on: {
CHECK_HOLD: "checking",
},
},
// read lock to see if we still have it
checking: {
on: {
ACQUIRED: "#acquired",
HELD: "holding",
LOCKED: "#acquiring",
},
},
},
},
// final states
acquired: {
id: "acquired",
type: "final",
},
timed_out: {
id: "timed_out",
type: "final",
},
},
},
{
actions: {
resetTotalHeldTime: assign({
totalHeldTime: 0,
}),
updateTotalHeldTime: assign({
totalHeldTime: (ctx, evt) => {
return ctx.totalHeldTime + lockConfig.checkDelayMs;
},
}),
setWaitTime: assign({
waitTime: (ctx, evt) => {
return randomInt(lockConfig.minWaitTimeMs, lockConfig.maxWaitTimeMs);
},
}),
resetTotalWaitTime: assign({
totalWaitTime: 0,
}),
updateTotalWaitTime: assign({
waitTime: 0,
totalWaitTime: (ctx, evt) => {
return ctx.totalWaitTime + ctx.waitTime;
},
}),
},
}
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment