v4 Cache.get: a caller that joins an abandoned lookup fails with an interruption it did not ask for
Los mantenedores suelen responder en 1 día
Nadie ha tomado este issue todavía.
Evaluación
- Dificultad
- 4/5
- Tiempo estimado
- 3-5 días
- Aptitud para principiantes
- 42/100
- Tipo de issue
- Error
- Claridad
- Bien especificado
- Estado de actividad
- Activo
- Stack tecnológico
- typescript
Línea de trabajo
The report points to Cache.get and EntryImpl.await; start by tracing how callers join an entry, how awaiters is updated, and how the lookup fiber or Deferred completes. Reproduce the timing in the issue’s TypeScript example, then compare the behavior on the v4 branch and main. Done means a caller that did not leave receives the lookup’s result or its own failure, not another caller’s interruption.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
Version: effect 4.0.0-beta.107 (the v4 line developed in Effect-TS/effect-smol, which does not take issues from outside the org).
Cache.get can fail a caller with an interrupt-only cause even though nothing interrupted that caller. It happens when the caller joins a lookup that another caller abandoned.
Reproduction (effect 4.0.0-beta.107, Bun 1.4.3)
import { Cache, Cause, Effect, Exit, Fiber } from "effect"
const program = Effect.gen(function* () {
let lookups = 0
const cache = yield* Cache.make({
capacity: 10,
// A lookup that cannot stop at once, like a spawned process or a blocked query
lookup: (_key: string) =>
Effect.sync(() => ++lookups).pipe(
Effect.andThen(Effect.sleep("300 millis").pipe(Effect.uninterruptible)),
Effect.as("value")
)
})
const a = yield* Cache.get(cache, "k").pipe(Effect.forkChild)
yield* Effect.sleep("50 millis")
yield* Fiber.interrupt(a).pipe(Effect.forkChild) // the only waiting caller gives up
yield* Effect.sleep("50 millis")
const b = yield* Effect.exit(Cache.get(cache, "k")) // b is never interrupted
console.log(Exit.isFailure(b) && Cause.hasInterruptsOnly(b.cause)) // true
const c = yield* Effect.exit(Cache.get(cache, "k"))
console.log(Exit.isSuccess(c), lookups) // true 2
})
Effect.runPromise(program)
What happens
When the last caller waiting on an entry leaves, the cache interrupts the lookup fiber (in 4.0.0-beta.107, EntryImpl.await calls fiberInterrupt once awaiters reaches 0). A caller that calls get before that fiber has exited finds the entry still in the map. It joins the fiber and receives its interrupted exit. Any catchCause above that caller then sees an interrupt-only cause, which looks exactly like a cancellation of the caller itself.
On main the lookup runs inside the first caller's fiber (effect.onExit(self.lookup(key), …) completes the shared Deferred with that fiber's exit). Interrupting that first caller would complete the Deferred with its interruption for every joiner. That conclusion comes from reading the code; I have not run it.
Expected
A caller that was not interrupted should get the lookup's value, or a failure of the lookup's own. One way to get there: the lookup is owned by the cache rather than by its first caller, and a caller that leaves stops only its own wait.
Impact
We hit this in a desktop app: a request that joined a repository lookup, which a timed-out snapshot had abandoned, ended interrupted. That stopped the user's first message from starting a session until they sent a second one. Thanks to @dahli4, whose trace from their own machine pinned it down. On our side we now run lookups in a scope the cache's owner holds, and retry a joiner that got an interruption it did not ask for.
- Lenguaje dominante
- TypeScript
- Estrellas
- 16.7k
- Forks
- 808
- Merge medio
- 10 h 7 min
- PR fusionados (30 d)
- 808
Preparar el entorno
Este proyecto no incluye contenedor de desarrollo, Dockerfile ni guía de contribución, así que la configuración corre por tu cuenta: empieza por su README y consulta nuestra guía para la primera contribución para los pasos generales.
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de Effect-TS/effect
-
Support {self: this} for fnUntracedPosiblemente ocupada @ArjunCodess la tomó hace 32 días. Abiertoenhancement
Dificultad 2/5 1-3 horas Aptitud para principiantes 70/100
Effect-TS/effect#8101 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
Dificultad 3/5 1-2 días Aptitud para principiantes 72/100
Los mantenedores suelen responder en 1 día
-
Typed unix socket and TLS options for `BunHttpClient` and `DenoHttpClient`Posiblemente ocupada @effect-bot la tomó hace 1 día. Abiertodocker-made-me-do-it enhancement platform
Effect-TS/effect#9687 · 1 asignado ·
Los mantenedores suelen responder en 1 día
-
RFC 9457 Problem Details for HttpApi errorsPosiblemente ocupada @effect-bot la tomó hoy. Abiertodocker-made-me-do-it enhancement
Dificultad 5/5 Más de una semana Aptitud para principiantes 20/100
Los mantenedores suelen responder en 1 día
-
Typed parsers and formatters for common HTTP header valuesPosiblemente ocupada @effect-bot la tomó hace 1 día. Abiertodocker-made-me-do-it enhancement
Effect-TS/effect#9685 · 1 asignado ·
Los mantenedores suelen responder en 1 día
Todos los issues de Effect-TS/effect
Issues similares
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 68/100
chaitin/MonkeyCode#1437 ·
Los mantenedores suelen responder en 1 día
-
rtdb-info-connected-order test: unhandled 'connection is closed' rejection fails the CLI suiteAbierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 69/100
carbon-design-system/carbon-ai-chat#2615 ·
Los mantenedores suelen responder en 1 día
-
e2e-failure ready-to-code
Dificultad 2/5 1-3 horas Aptitud para principiantes 76/100
redhat-developer/rhdh-plugin-export-overlays#4486 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
[Bug]: fileUploadMatrix.test.ts URL case does a real DNS lookup and fails offlinePosiblemente ocupada @r2jaff la tomó hoy. Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
ComposioHQ/composio#5054 ·
Los mantenedores suelen responder en 1 día