Explicit sub-orchestration id collision with a *running* instance hangs the parent silently
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
- 48/100
- Tipo de issue
- Error
- Claridad
- Bastante claro
- Estado de actividad
- Tranquilo
- Stack tecnológico
- rust
- Área
- backend, distributed-systems
Línea de trabajo
Comienza en process_orchestration_item y compara la ruta normal de StartOrchestration con terminal_collision_notifications. Reproduce el caso de shared-child usando schedule_sub_orchestration_with_id y luego inspecciona cómo se gestionan el historial existente y el enlace al parent registrado. Se considera terminado cuando la colisión en curso ya no deja a p2 esperando silenciosamente y el comportamiento y las pruebas están alineados con la dirección elegida.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
Summary
When a parent schedules a sub-orchestration with an explicit instance id that already names a running (non-terminal) instance, the parent waits forever. There is no error, no notification, and no log line.
The terminal half of this collision is handled — terminal_collision_notifications in the orchestration dispatcher fails the parent fast when the target id names a terminal instance. The running half has no equivalent.
| Colliding instance is… | Outcome |
|---|---|
| terminal | parent fails fast ✅ |
| running | parent hangs silently ❌ |
Arguably "running" is the likelier half: two parents racing on the same id is most plausible precisely when the child is long-lived.
Reproduction
Two unrelated parents pass the same explicit id to schedule_sub_orchestration_with_id. No reserved marker, no provider bypass — public API only.
let parent = |ctx: OrchestrationContext, _i: String| async move {
ctx.schedule_sub_orchestration_with_id("Child", "shared-child", "x").await
};
// Child parks on an external event so it stays Running.
let child = |ctx: OrchestrationContext, _i: String| async move {
ctx.schedule_wait("Go").await;
Ok("child-done".to_string())
};
client.start_orchestration("p1", "Parent", "").await?; // creates "shared-child", parks
client.start_orchestration("p2", "Parent", "").await?; // same id, still running
Observed:
child status after p1: Running
p2: HUNG (timeout)
p1 final: Completed { output: "ok:child-done" }
p2 final: Running <- forever
p2's StartOrchestration is absorbed as a duplicate start for an existing instance. The child eventually completes and notifies only p1 — its recorded parent. p2 gets nothing.
Why it happens
terminal_collision_notifications is only invoked from the terminal fast-ack path in process_orchestration_item:
if temp_history_mgr.is_completed || temp_history_mgr.is_failed || (…CAN…) {
let orchestrator_items = self.terminal_collision_notifications(&item).await;
…
}
A colliding start against a running instance never reaches that branch. It falls through to normal processing, where it is deduplicated against the existing history and silently dropped.
Scope
Only reachable when the child id is caller-chosen — schedule_sub_orchestration_with_id, schedule_orchestration (detached), or an id already created by Client::start_orchestration. Auto-generated ids cannot collide: they embed both the parent instance id and its execution.
Pre-existing; not introduced by #28. Splitting out so that PR stays scoped.
Possible directions
- Detect in the normal path — when an incoming
StartOrchestrationtargets an instance whose recorded parent link differs from the incoming one, notify the incoming parent withSubOrchFailed. Symmetric with the terminal case, but needs care to avoid the false-positive class that the terminal-path parent comparison originally had (see #28 discussion). - Make it loud instead of silent — cheapest option. Log an error whenever a
StartOrchestrationis discarded for an already-existing instance. Fixes no hang but removes the silence. - Reject at schedule time — not possible in general; the scheduling parent has no way to know the id is taken without a provider read.
- Lenguaje dominante
- Rust
- Estrellas
- 226
- Forks
- 62
- Merge medio
- 20 h 46 min
- PR fusionados (30 d)
- 6
Preparar el entorno
- Sin Dockerfile ni archivo de Docker Compose
- Tiene una plantilla de pull request
- Leer la guía de contribución
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 microsoft/duroxide
-
bug
Dificultad 3/5 1-2 días Aptitud para principiantes 74/100
Los mantenedores suelen responder en 1 día
-
One failed session lock renewal loses the session: no retry, no log, no signal to running activitiesAbiertobug
Dificultad 4/5 3-5 días Aptitud para principiantes 30/100
Los mantenedores suelen responder en 1 día
-
bug
Dificultad 3/5 1-2 días Aptitud para principiantes 72/100
Los mantenedores suelen responder en 1 día
-
bug
Dificultad 5/5 Más de una semana Aptitud para principiantes 38/100
Los mantenedores suelen responder en 1 día
-
bug
Dificultad 4/5 3-5 días Aptitud para principiantes 48/100
Los mantenedores suelen responder en 1 día
Todos los issues de microsoft/duroxide
Issues similares
-
area:desktop priority:p2 type:bug
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
Los mantenedores suelen responder en 1 día
-
Dificultad 1/5 1-3 horas Aptitud para principiantes 88/100
fritzprix/libr-agent#2165 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 69/100
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 82/100
-
area:ecosystem bug
Dificultad 2/5 1-3 horas Aptitud para principiantes 75/100
Chelis-Lang/chelis#3942 ·
Los mantenedores suelen responder en 1 día