Skip to content

Instantly share code, notes, and snippets.

@kdgerona
Last active November 7, 2020 01:06
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 kdgerona/ee796c6d0b12e9142df33b775c226b57 to your computer and use it in GitHub Desktop.
Save kdgerona/ee796c6d0b12e9142df33b775c226b57 to your computer and use it in GitHub Desktop.
Generated by XState Viz: https://xstate.js.org/viz
// GenerateWorkers
const worker_data = [
{worker_id: 0},
{worker_id: 1},
{worker_id: 2},
]
const workers_config = worker_data.reduce((acc, curr) => {
const { worker_id } = curr
return {
...acc,
[`worker${worker_id}`]: {
id: `worker${worker_id}`,
initial: 'initialization',
states: {
initialization: {
on: {
[`CONNECT_TO_TRACKER${worker_id}`]: 'ready',
[`CONNECT_FAILED${worker_id}`]: 'reconnect',
}
},
ready: {
entry: `workerReady${worker_id}`,
on: {
[`USER_REQUEST_WORKER${worker_id}`]: {
actions: 'processingLog',
target: 'processing'
}
}
},
processing: {
entry: `acknowledgement${worker_id}`,
initial: 'checkingUser',
onDone: 'ready',
states: {
checkingUser: {
after: {
3000: 'validating'
},
actions: 'checkingUser'
},
validating: {
after: {
3000: 'done'
},
actions: 'validating'
},
done: {
type: 'final'
}
}
},
reconnect: {
after: {
3000: 'initialization'
}
}
}
},
}
},{})
// END
// Genrating implementations which includes worker actions
// const trackerImplementations = worker_data.reduce((acc, curr) => {
// const { worker_id } = curr
// return {
// ...acc,
// services: {
// startInterval: () => {
// return new Promise((resolve) => {
// return setTimeout(() => resolve(), 1000)
// })
// },
// distributeToWorker: (context) => (send) => {
// const { worker_list } = context;
// const rand_result = getRandomInt(worker_list.length)
// send(`USER_REQUEST_WORKER${rand_result}`)
// send('TASK_DEQUEUE')
// }
// },
// actions: {
// addQueueRequest: assign({
// enqueue: ((context) => context.enqueue + 1)
// }),
// taskDequeue: assign({
// dequeue: ((context) => context.dequeue + 1)
// }),
// startTicker: send('START_TICKER', 'ticker'),
// [`connectWorker${worker_id}`]: assign({
// worker_list: (context) => [...context.worker_list, { id: `WORKER${worker_id}`, status: 'ready' }],
// }),
// },
// delays: {},
// guards: {
// checkEnqueues: (context) => context.enqueue === context.dequeue,
// checkTaskQueue: (context) => context.enqueue !== context.dequeue,
// },
// activities: {},
// }
// },{})
const workerImplementations = worker_data.reduce((acc, curr) => {
const { services, actions, delays, guards, activities} = acc
const { worker_id } = curr
return {
services: {...services},
actions: {
...actions,
[`workerReady${worker_id}`]: assign({
worker_list: (context) => [...context.worker_list, { id: `WORKER${worker_id}`, status: 'ready' }],
}),
[`acknowledgement${worker_id}`]: send('TASK_ACKNOWLEDGED'),
},
delays: {...delays},
guards: {...guards},
activities: {...activities},
}
},{})
// END
// Helper function for randomizing
const getRandomInt = (readyWorkersCount) => {
return Math.floor(Math.random() * Math.floor(readyWorkersCount));
}
// const workerImplementations = {
// services: {},
// actions: {
// readyLog: () => console.log('Worker is ready to recieve queries!'),
// processingLog: () => console.log('Currently processing request'),
// checkingUser: () => console.log('Checking User existence in the database'),
// validating: () => console.log('Validating user credentials')
// },
// delays: {},
// guards: {},
// activities: {},
// }
// **** Traker ****
const context = {
worker_list: [],
ready_workers: [],
task_queue: [],
enqueue: 0,
dequeue: 0,
}
const trackerConfig = {
id: 'tracker',
initial: 'tracking',
context,
type: 'parallel',
states: {
tracking: {
type: 'parallel',
initial: 'ticker',
states: {
listerner: {
id: 'listerner',
initial: 'idle',
states: {
idle: {
on: {
"START_TICKER" : 'interval'
}
},
interval: {
invoke: {
src: 'startInterval',
onDone: 'checking'
}
},
checking: {
on: {
"": [
{
target: 'interval',
cond: 'checkEnqueues'
},
{
target: 'stop'
}
]
}
},
stop: {
entry: send('START_LOAD_DISTRIBUTION', 'balancing'),
on: {
"": 'idle'
}
}
}
},
balancer: {
id: 'balancer',
initial: 'idle',
states: {
idle: {
on: {
START_LOAD_DISTRIBUTION: 'checkTaskQueue',
// TEST: {
// actions: send('USER_REQUEST_WORKER1')
// }
}
},
checkTaskQueue: {
on: {
"": [
{
target: 'distribute',
cond: 'checkTaskQueue'
},
{
target: 'idle',
actions: ['startTicker']
}
]
}
},
distribute: {
entry: 'distributeToWorker',
// invoke: {
// src: 'distributeToWorker'
// },
// after: {
// 3000: 'checkTaskQueue'
// }
on: {
// TASK_DEQUEUE: {
// target: 'checkTaskQueue',
// actions: ['taskDequeue']
// },
TASK_ACKNOWLEDGED: {
target: 'checkTaskQueue',
actions: ['taskDequeue', 'shiftWorker']
},
}
}
}
},
},
on: {
SEND_REQUEST: {
actions: 'addQueueRequest'
}
}
},
worker: {
type: 'parallel',
states: {
...workers_config
}
}
},
on: {
START_MACHINE: {
actions: send('START_TICKER')
}
}
}
const trackerImplementations = {
services: {
...workerImplementations.services,
startInterval: () => {
return new Promise((resolve) => {
return setTimeout(() => resolve(), 1000)
})
},
// distributeToWorker: (context) => (send) => {
// const { worker_list } = context;
// const rand_result = getRandomInt(worker_list.length)
// send(`USER_REQUEST_WORKER${rand_result}`)
// // send('TASK_DEQUEUE')
// }
},
actions: {
...workerImplementations.actions,
addQueueRequest: assign({
enqueue: ((context) => context.enqueue + 1)
}),
taskDequeue: assign({
dequeue: ((context) => context.dequeue + 1)
}),
startTicker: send('START_TICKER', 'ticker'),
distributeToWorker: send((context) => {
const { worker_list } = context;
const rand_result = getRandomInt(worker_list.length)
return `USER_REQUEST_WORKER${rand_result}`
}),
shiftWorker: assign({
worker_list: (context) => {
// [...context.worker_list, { id: 'WORKER0', status: 'ready' }],
const [_,...newWorkerList] = context.worker_list
return newWorkerList
}
}),
},
delays: {...workerImplementations.delays},
guards: {
...workerImplementations.guards,
checkEnqueues: (context) => context.enqueue === context.dequeue,
checkTaskQueue: (context) => context.enqueue !== context.dequeue,
},
activities: {...workerImplementations.activities},
}
// *** Machine ***
const machine = Machine(trackerConfig,trackerImplementations);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment