| 122 | |
| 123 | const router = Router(Rsc)({ |
| 124 | *effect(match) { |
| 125 | return match({ |
| 126 | StreamEtag: () => |
| 127 | Effect |
| 128 | .gen(function*() { |
| 129 | // 1) Acquire the request-scoped ContextMap. Fails (dies) if the |
| 130 | // container is still the default "root" — which would mean |
| 131 | // RequestContextMiddleware did not run for this request. |
| 132 | const ctxMap = yield* getContextMap.pipe(Effect.orDie) |
| 133 | // 2) Seed an etag BEFORE handing back the Stream. This write is |
| 134 | // what the per-chunk readers below verify. |
| 135 | ctxMap.set(ETAG_ID, ETAG_VALUE) |
| 136 | // 3) Emit three values 100ms apart so chunks are produced AFTER |
| 137 | // the outer Effect that built the response has returned. Each |
| 138 | // emission re-reads the etag from the request-scoped ContextMap. |
| 139 | return Stream.fromIterable([0, 1, 2]).pipe( |
| 140 | Stream.mapEffect(() => |
| 141 | Effect.sleep("100 millis").pipe( |
| 142 | Effect.flatMap(() => getContextMap.pipe(Effect.orDie)), |
| 143 | Effect.map((m) => m.get(ETAG_ID) === ETAG_VALUE ? 1 : 0) |
| 144 | ) |
| 145 | ) |
| 146 | ) |
| 147 | }) |
| 148 | .pipe(Stream.unwrap), |
| 149 | StreamWithEtag: ({ value }: { readonly value: string }) => |
| 150 | Effect |
| 151 | .gen(function*() { |
| 152 | const ctxMap = yield* getContextMap.pipe(Effect.orDie) |
| 153 | ctxMap.set(SHARED_KEY, value) |
| 154 | return Stream.fromIterable([0, 1, 2]).pipe( |
| 155 | Stream.mapEffect(() => |
| 156 | Effect.sleep("100 millis").pipe( |
| 157 | Effect.flatMap(() => getContextMap.pipe(Effect.orDie)), |
| 158 | Effect.map((m) => m.get(SHARED_KEY) ?? MISSING) |
| 159 | ) |
| 160 | ) |
| 161 | ) |
| 162 | }) |
| 163 | .pipe(Stream.unwrap), |
| 164 | ReadEtagOnce: () => getContextMap.pipe(Effect.orDie, Effect.map((m) => m.get(SHARED_KEY) ?? MISSING)) |
| 165 | }) |
| 166 | } |
| 167 | }) |
| 168 | |
| 169 | const RpcRouterLayer = matchAll({ router }) |