Skip to content

Instantly share code, notes, and snippets.

@sergeysova
Last active October 31, 2021 10:41
Show Gist options
  • Save sergeysova/289a6948a468447c21c9a1815a9e667c to your computer and use it in GitHub Desktop.
Save sergeysova/289a6948a468447c21c9a1815a9e667c to your computer and use it in GitHub Desktop.
import {
allSettled,
attach,
createDomain,
createEvent,
createStore,
fork,
forward,
guard,
sample,
Scope
} from 'effector';
import Koa from 'koa';
import Router from 'koa-router';
import Redis from 'ioredis';
const domain = createDomain();
domain.onCreateEffect((effect) => {
const sid = effect.sid
effect.watch((val) => {
console.log(`Effect "${sid}" call with value: ${val}`);
});
effect.doneData.watch((val) => {
console.log(`Effect "${sid}" done with value: ${val}`);
});
effect.failData.watch((val) => {
console.log(`Effect "${sid}" fail with value: ${val}`);
});
})
domain.onCreateEvent((event) => {
const sid = event.sid
event.watch((val) => {
console.log(`Event "${sid}" call with value: ${val}`);
});
})
domain.onCreateStore((store) => {
const sid = store.sid
store.watch((state, val) => {
console.log(`Store "${sid}" mutation with value: ${val}`);
console.log(`Store "${sid}" mutation, current state: ${state}`);
});
})
interface Context {
scope: Scope;
}
const $login = createStore('');
const increment = createEvent()
const decrement = createEvent()
const reset = createEvent()
const pullCounterFx = attach({
source: $login,
async effect(login) {
const count = await redis.get(`${login}:counter`);
return Number(count ?? 0);
}
})
const $counter = createStore(0)
.on(increment, (state) => state + 1)
.on(decrement, (state) => state - 1)
.on(pullCounterFx.doneData, (_, value) => value)
.reset(reset)
const pushCounterFx = attach({
source: [$counter, $login],
async effect([count, login]) {
await redis.set(`${login}:counter`, count);
return count;
}
})
const handleMethods = createEvent<'increment' | 'decrement' | 'reset'>();
forward({from: handleMethods, to: pullCounterFx});
const runOperation = sample({clock: pullCounterFx.doneData, source: handleMethods})
guard({source: runOperation, filter: operation => operation === 'increment', target: increment})
guard({source: runOperation, filter: operation => operation === 'decrement', target: decrement})
guard({source: runOperation, filter: operation => operation === 'reset', target: reset})
sample({
clock: [increment, decrement, reset],
target: pushCounterFx,
})
const $result = createStore(0);
$result.on(pushCounterFx.doneData, (_, counter) => counter)
const app = new Koa<{}, Context>();
const router = new Router<{}, Context>();
const redis = new Redis();
app.use(async (context, next) => {
context.scope = fork();
await next()
});
router.post('/increment', async (ctx) => {
await allSettled(handleMethods, { params: 'increment', scope: ctx.scope })
ctx.body = ctx.scope.getState($result)
});
router.post('/decrement', async (ctx) => {
await allSettled(handleMethods, { params: 'decrement', scope: ctx.scope })
ctx.body = ctx.scope.getState($result)
});
router.post('/reset', async (ctx) => {
await allSettled(handleMethods, { params: 'reset', scope: ctx.scope })
ctx.body = ctx.scope.getState($result)
});
app.use(router.routes());
app.listen(4000);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment