Skip to content

Commit 04d5aaf

Browse files
dagda1cowboyd
andauthored
Simplify createSimulation and destroySimulation (#174)
* remove createSimulation from effects * remove simulation from state on teardown * add changeSet * fix changeset * Update packages/server/src/operation-context.ts Co-authored-by: Charles Lowell <cowboyd@frontside.com> * remove createSimulation from effects * type task * remove defaultCommandTimeout from cypress.json * remove defaultCommandTimeout from cypress.json Co-authored-by: Charles Lowell <cowboyd@frontside.com>
1 parent 175a0f4 commit 04d5aaf

File tree

9 files changed

+95
-62
lines changed

9 files changed

+95
-62
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
"@simulacrum/server": minor
3+
---
4+
Simplify createSimulation and destroySimulation by removing them from the effects.

packages/server/src/effects.ts

Lines changed: 0 additions & 16 deletions
This file was deleted.
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import { Task } from 'effection';
2+
import { ServerState, SimulationOptions, SimulationState, Simulator } from './interfaces';
3+
import { OperationContext } from './schema/context';
4+
import { v4 } from 'uuid';
5+
import { Slice } from '@effection/atom';
6+
import { createSimulation } from './simulation';
7+
8+
type NewId = (() => string) | typeof v4;
9+
10+
export function createOperationContext(atom: Slice<ServerState>, scope: Task, newid: NewId, simulators: Record<string, Simulator>): OperationContext {
11+
let simulationsMap = new Map<string, Task>();
12+
13+
return {
14+
atom,
15+
scope,
16+
async createSimulation(
17+
simulator: string,
18+
options: SimulationOptions,
19+
debug: boolean
20+
): Promise<SimulationState> {
21+
let simulationId = options.key ?? newid();
22+
let existing = simulationsMap.get(simulationId);
23+
24+
if (!!existing) {
25+
await existing.halt();
26+
}
27+
28+
let slice = atom.slice("simulations", simulationId);
29+
30+
slice.set({
31+
id:simulationId,
32+
status: 'new',
33+
simulator,
34+
options,
35+
services: [],
36+
scenarios: {},
37+
store: {},
38+
debug,
39+
});
40+
41+
await scope.run(function*() {
42+
let simulationTask: Task = yield scope.spawn(function* () {
43+
yield createSimulation(slice, simulators);
44+
45+
try {
46+
yield;
47+
} finally {
48+
simulationsMap.delete(simulationId);
49+
slice.remove();
50+
}
51+
});
52+
53+
simulationsMap.set(simulationId, simulationTask);
54+
55+
yield slice.filter(({ status }) => status === 'running').expect();
56+
});
57+
58+
return slice.get();
59+
},
60+
async destroySimulation(simulationId: string) {
61+
let simulation = simulationsMap.get(simulationId);
62+
63+
if(!simulation) {
64+
return false;
65+
}
66+
67+
await simulation.halt();
68+
69+
return true;
70+
},
71+
newid
72+
};
73+
}

packages/server/src/schema/context.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
import { Slice } from '@effection/atom';
22
import { Task } from 'effection';
3-
import { ServerState } from '../interfaces';
3+
import { ServerState, SimulationOptions, SimulationState } from '../interfaces';
44

55
export interface OperationContext {
66
scope: Task;
77
atom: Slice<ServerState>;
8+
createSimulation(
9+
simulator: string,
10+
options: SimulationOptions,
11+
debug: boolean): Promise<SimulationState>;
12+
destroySimulation(id: string): Promise<boolean>;
813
newid(): string;
914
}

packages/server/src/schema/resolvers.ts

Lines changed: 3 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -22,46 +22,14 @@ export interface CreateSimulationParameters {
2222
export const createSimulation: Resolver<CreateSimulationParameters, SimulationState> = {
2323
async resolve(args, ctx) {
2424
let { simulator, options = {}, debug = false } = args;
25-
let { atom, scope, newid } = ctx;
2625

27-
let id = options.key ?? newid();
28-
29-
let simulation = atom.slice("simulations", id);
30-
31-
if(simulation.get()?.status === 'running') {
32-
await destroySimulation.resolve({ id }, ctx);
33-
}
34-
35-
if(['halted', 'destroying'].includes(simulation.get()?.status)) {
36-
await scope.run(simulation.filter((sim) => typeof sim === 'undefined').expect());
37-
}
38-
39-
simulation.set({
40-
id,
41-
status: 'new',
42-
simulator,
43-
options,
44-
services: [],
45-
scenarios: {},
46-
store: {},
47-
debug,
48-
});
49-
50-
return scope.run(simulation.filter(({ status }) => status !== 'new').expect());
26+
return await ctx.createSimulation(simulator, options, debug);
5127
}
5228
};
5329

5430
export const destroySimulation: Resolver<{ id: string }, boolean> = {
55-
async resolve({ id }, { atom, scope }) {
56-
let simulation = atom.slice("simulations", id);
57-
if (simulation.get()) {
58-
simulation.slice("status").set("destroying");
59-
await scope.run(simulation.filter(({ status }) => status == "halted").expect());
60-
simulation.remove();
61-
return true;
62-
} else {
63-
return false;
64-
}
31+
async resolve({ id }, { destroySimulation }) {
32+
return await destroySimulation(id);
6533
}
6634
};
6735

packages/server/src/server.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,14 @@ import { v4 } from 'uuid';
77
import { schema } from './schema/schema';
88
import { ServerOptions, ServerState } from './interfaces';
99
import { Server, createServer } from './http';
10-
import { OperationContext } from './schema/context';
1110

1211
export { Server, createServer } from './http';
1312

14-
import { createEffects } from './effects';
1513
import { stableIds } from './faker';
1614
import { createWebSocketTransport } from './websocket-transport';
1715
import { Resource } from 'effection';
16+
import { createOperationContext } from './operation-context';
17+
import { createLogger } from './effects/logging';
1818

1919
const defaults = {
2020
simulators: {},
@@ -33,7 +33,7 @@ export function createSimulationServer(options: ServerOptions = defaults): Resou
3333
simulations: {}
3434
});
3535

36-
let context: OperationContext = { atom, scope, newid };
36+
let context = createOperationContext(atom, scope, newid, simulators);
3737

3838
let app = express()
3939
.use(cors())
@@ -45,7 +45,7 @@ export function createSimulationServer(options: ServerOptions = defaults): Resou
4545

4646
yield createWebSocketTransport(context, server.http);
4747

48-
yield createEffects(atom, simulators);
48+
yield createLogger(atom);
4949

5050
return server;
5151
}

packages/server/src/simulation.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { label, spawn } from 'effection';
1+
import { label, Operation, spawn, Task } from 'effection';
22
import { assert } from 'assert-ts';
33
import { Effect, map } from './effect';
44
import express, { raw } from 'express';
@@ -69,7 +69,7 @@ function normalizeServiceCreator(service: ServiceCreator): ResourceServiceCreato
6969
};
7070
}
7171

72-
function createSimulation (slice: Slice<SimulationState>, simulators: Record<string, Simulator>) {
72+
export function createSimulation (slice: Slice<SimulationState>, simulators: Record<string, Simulator>): Operation<Task<void>> {
7373
return spawn(function* () {
7474
try {
7575
yield function * errorBoundary() {

packages/server/src/websocket-transport.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import { OperationContext } from './schema/context';
1515
*/
1616

1717

18-
export function createWebSocketTransport({ atom, newid }: OperationContext, server: HTTPServer): Resource<void> {
18+
export function createWebSocketTransport(context: OperationContext, server: HTTPServer): Resource<void> {
1919
return {
2020
*init(scope) {
2121
let transport = makeServer<Task>({
@@ -29,8 +29,7 @@ export function createWebSocketTransport({ atom, newid }: OperationContext, serv
2929
variableValues,
3030
document: parse(message.payload.query),
3131
contextValue: {
32-
atom,
33-
newid,
32+
...context,
3433
scope: extra
3534
}
3635
};

packages/server/test/person.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ describe('person simulator', () => {
2121
simulation = yield client.createSimulation("person");
2222
});
2323

24-
describe('positing a person', () => {
24+
describe('posting a person', () => {
2525
let person: Scenario<{ name: string}>;
2626
beforeEach(function*() {
2727
person = yield client.given(simulation, "person");

0 commit comments

Comments
 (0)