thefrontside / thefrontside/effection

`.all()` creates a new Scope

Open
#897 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
856
Forks
39
Avg merge
2d 8h
Merged PRs (30d)
8

Description

I'm not sure what the reasoning behind this is, but it appears that .all() creates a new Scope when it's called, but isn't documented as such. This can cause surprising behavior: an example from some code I was writing tonight looks something like this:

const ops: Operation<int>[] = [/* some array of operations that should run simultaneously */];
const tasks = yield* all(ops.map((op) => spawn(() => op))); /* throws error: Halted, surprising */
for (const task of tasks) {
    const result = yield* task;
    /* do something async with result, say:*/
    yield* sleep(result);
}

I believe this is because the operations all start, returning a task, but when the Scope from all is destroyed as a result of it returning to the parent, the scope for all the spawned operations is also dead.

If I just wanted to run them simultaneously and deal with the results, I could just use .all directly and skip this, but in this case I want to run all the operations simultaneously and then do something else asynchronous with them.

In any case, this is workaround-able by simply emulating what .all does without creating a new scope, but it seems strange to me that the new scope is needed in the first place, as it seems to be just an extra call wrapping the whole function.

Is this intentional behavior?

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by locating the implementation of .all() and its Scope/call wrapping, then reproduce the TypeScript example using spawn, sleep, and returned tasks. Check how scope lifetime is intended to work; done means the behavior is clarified and either documented or covered by an agreed regression test.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.