Skip to content

Commit 59f83af

Browse files
authored
Merge pull request #1017 from thefrontside/v4-resource-priority
🐛 run resources at the priority level of their caller
2 parents eff9c3b + e46ac5c commit 59f83af

File tree

5 files changed

+42
-9
lines changed

5 files changed

+42
-9
lines changed

lib/contexts.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ export const Routine = createContext<Coroutine<unknown>>(
55
"@effection/coroutine",
66
);
77

8-
export const Generation = createContext<number>(
8+
export const Priority = createContext<number>(
99
"@effection/scope.generation",
1010
0,
1111
);

lib/coroutine.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Generation } from "./contexts.ts";
1+
import { Priority } from "./contexts.ts";
22
import { DelimiterContext } from "./delimiter.ts";
33
import { ReducerContext } from "./reducer.ts";
44
import { Ok } from "./result.ts";
@@ -32,7 +32,7 @@ export function createCoroutine<T>(
3232
routine.data.exit((exitResult) => {
3333
routine.data.exit = (didExit) => didExit(Ok());
3434
reducer.reduce([
35-
scope.expect(Generation),
35+
scope.expect(Priority),
3636
routine,
3737
exitResult.ok ? result : exitResult,
3838
scope.expect(DelimiterContext).validator,
@@ -44,7 +44,7 @@ export function createCoroutine<T>(
4444
routine.data.exit((exitResult) => {
4545
routine.data.exit = (didExit) => didExit(Ok());
4646
reducer.reduce([
47-
scope.expect(Generation),
47+
scope.expect(Priority),
4848
routine,
4949
exitResult.ok ? result : exitResult,
5050
scope.expect(DelimiterContext).validator,

lib/resource.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import { suspend } from "./suspend.ts";
2-
import { spawn } from "./spawn.ts";
32
import type { Operation } from "./types.ts";
4-
import { trap } from "./task.ts";
3+
import { createTask, trap } from "./task.ts";
54
import { Ok } from "./result.ts";
65
import { useCoroutine } from "./coroutine.ts";
6+
import type { ScopeInternal } from "./scope-internal.ts";
7+
import { Priority } from "./contexts.ts";
78

89
/**
910
* Define an Effection [resource](https://frontside.com/effection/docs/resources)
@@ -57,7 +58,16 @@ export function resource<T>(
5758
// establishing a control boundary lets us catch errors in
5859
// resource initializer
5960
return yield* trap<T>(function* () {
60-
yield* spawn(() => op(provide));
61+
let { scope, start } = createTask<void>({
62+
owner: caller.scope as ScopeInternal,
63+
operation: () => op(provide),
64+
});
65+
66+
// a resource runs at the priority of its parent
67+
scope.set(Priority, caller.scope.expect(Priority));
68+
69+
start();
70+
6171
return (yield {
6272
description: "await resource",
6373
enter: () => (uninstalled) => uninstalled(Ok()),

lib/scope-internal.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Children, Generation } from "./contexts.ts";
1+
import { Children, Priority } from "./contexts.ts";
22
import { Err, Ok, unbox } from "./result.ts";
33
import { createTask } from "./task.ts";
44
import type { Context, Operation, Scope, Task } from "./types.ts";
@@ -57,7 +57,7 @@ export function createScopeInternal(
5757
},
5858
});
5959

60-
scope.set(Generation, scope.expect(Generation) + 1);
60+
scope.set(Priority, scope.expect(Priority) + 1);
6161
scope.set(Children, new Set());
6262
parent?.expect(Children).add(scope);
6363

test/resource.test.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,29 @@ describe("resource", () => {
8484

8585
expect(state.status).toEqual("pending");
8686
});
87+
88+
it("does not relinquish control when a resource initialized synchronously", async () => {
89+
let sequence: number[] = [];
90+
91+
await run(function* () {
92+
sequence.push(1);
93+
94+
let task = yield* spawn(function* () {
95+
sequence.push(4);
96+
});
97+
98+
yield* resource<void>(function* (provide) {
99+
sequence.push(2);
100+
yield* provide();
101+
});
102+
103+
sequence.push(3);
104+
105+
yield* task;
106+
});
107+
108+
expect(sequence).toEqual([1, 2, 3, 4]);
109+
});
87110
});
88111

89112
function createResource(container: State): Operation<State> {

0 commit comments

Comments
 (0)