[claude] Sync head truncates HybridDateTime to milliseconds, permanently stranding commits
Los mantenedores suelen responder en 4 días
Nadie ha tomado este issue todavía.
Evaluación
- Dificultad
- 4/5
- Tiempo estimado
- 3-5 días
- Aptitud para principiantes
- 35/100
- Tipo de issue
- Error
- Claridad
- Bien especificado
- Estado de actividad
- Activo
- Stack tecnológico
- csharp
- Área
- distributed-systems
Línea de trabajo
Comienza con QueryHelpers.GetSyncState y las dos rutas de GetMissingCommits en QueryHelpers.cs; después compara su orden con WhereAfter e inspecciona SyncState. Ejecuta las pruebas que cubren counter-sibling, stranded commits, clamp bursts y la sincronización de extremo a extremo en ambos backends sincronizables. La tarea estará terminada cuando los casos de pérdida descritos ya no dejen commits varados y toda la suite de pruebas pase correctamente.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
[Claude, autonomous]
[!TIP]
A starter branch is attached to this issue to jump-start the implementation:claude/harmony-issue-89-oga6ra• browse the diffIt takes the boringly-simple route instead of the full-precision one below: make the sync-head comparison inclusive on the millisecond (
>→>=) in bothGetMissingCommitspaths, so the head's whole millisecond is re-offered rather than stranded. Per-client the HLC is monotonic, so re-offering that millisecond can never leapfrog a commit. Re-applying a commit the remote already holds is idempotent (FilterExistingCommitsdrops it), so the only cost is re-sending the head-millisecond commits each sync. NoSyncStatewire-format change and no back-compat path needed.Tests cover every flavour of the bug and each fails before the one-line-per-path change: counter-sibling on the head millisecond, a stranded commit after the head advances (both on a whole-millisecond boundary, which the DB pre-filter drops, and with sub-millisecond ticks, which the in-memory guard drops), a full clamp burst, and an end-to-end sync across both syncable backends.
Bug. The per-client sync head is Max(DateTime).ToUnixTimeMilliseconds() (QueryHelpers.GetSyncState), and GetMissingCommits selects the push set with a strict > on that millisecond — both the DB pre-filter and the in-memory guard (QueryHelpers.cs:53,56). But commits carry microsecond DateTime and a Counter. Any commit sharing the head's millisecond fails ms > ms and is treated as already-synced: never offered, and the sync reports success. Once a later commit advances the head, the DB pre-filter excludes it too. The result is permanent, silent commit loss — usually just missing data, or a NotSupportedException in SnapshotWorker if the stranded commit was the create for an entity whose later edit did sync.
How several commits end up sharing one millisecond — HLC clamping. When the wall clock is at or behind lastDateTime, GetDateTime stamps successive commits with the same DateTime and an incrementing Counter. Two ways in: a peer's future-dated commit pulls the HLC ahead of local real time, or the local clock steps back. Either way, every commit made during the catch-up window shares one millisecond; per client, only the first that the server already holds survives, and the rest strand.
Fix. Make the head precision-complete: carry the full HybridDateTime (DateTime + Counter) per client and compare with (DateTime, Counter, Id) ordering, as WhereAfter already does. Per-client commits strictly increase in (DateTime, Counter), so a full-precision watermark is exact. SyncState is a client↔server wire type, so keep a back-compat path for clients still sending millisecond-only heads.
Related: #79 (same watermark weakness, ClientId-duplication variant; its per-client digest would also detect this loss); #7 (future-dated commits, one clamp trigger).
- Lenguaje dominante
- C#
- Estrellas
- 14
- Forks
- 4
- Merge medio
- 5 d 4 h
- PR fusionados (30 d)
- 13
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 sillsdev/harmony
-
enhancement
Dificultad 2/5 1-3 horas Aptitud para principiantes 84/100
Los mantenedores suelen responder en 4 días
-
Dificultad 5/5 Más de una semana Aptitud para principiantes 20/100
Los mantenedores suelen responder en 4 días
-
Dificultad 5/5 Más de una semana Aptitud para principiantes 35/100
Los mantenedores suelen responder en 4 días
-
bug Data bug
Dificultad 4/5 3-5 días Aptitud para principiantes 55/100
Los mantenedores suelen responder en 4 días
-
enhancement
Dificultad 3/5 1-2 días Aptitud para principiantes 58/100
Los mantenedores suelen responder en 4 días
Todos los issues de sillsdev/harmony
Issues similares
-
devtools
Dificultad 2/5 1-3 horas Aptitud para principiantes 82/100
Los mantenedores suelen responder en 1 día
-
clawsweeper:fix-shape-clear clawsweeper:needs-maintainer-review clawsweeper:no-new-fix-pr clawsweeper:not-repro-on-main impact:ux-release-blocker issue-rating: 🦪 silver shellfish P0
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
openclaw/openclaw-windows-node#1843 · 1 comentario · 1 reacción ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 66/100
-
kind:ux size:S type:bug
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
elsa-workflows/elsa-foundation#3256 ·
Los mantenedores suelen responder en 1 día
-
[Bug]: Revit selector reads process ids 2000-2099 as years (flaky AgentClientTests.AYearOrAProcessIdSelectsTheHost)Posiblemente ocupada @Wurschdhaud la tomó hoy. Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 83/100
pyrevitlabs/pyRevit#3817 ·
Los mantenedores suelen responder en 1 día