Project homepage Mailing List  Warmcat.com  API Docs  Github Mirror 
    npro  
 Modern all-safe Rust Network Protocol library supporting h1, h2, h3, ws, wt sans-IO and with socket IO + tls
git clone https://npro.rs/repo/npro
 
root / etc-sai-EXAMPLE
Author[]Andy Green <andy@warmcat.com> 2026-09-11 04:32 UTC
Committer[]Andy Green <andy@warmcat.com> 2026-09-11 04:32 UTC
Treea93bee1e058d7745ef6d705ac898a0f08c6ec955   Raw Patch
 
builder: issue strictly increasing log chunk timestamps per nspawn
builder: issue strictly increasing log chunk timestamps per nspawn

sai-web pages a task's logs 50 rows at a time, ordered by uid,timestamp
with a "timestamp > last delivered" cursor.  Any chunk that shares the
timestamp of the last row on a page is therefore never delivered.  On
unix lws_now_usecs() has microsecond resolution and collisions are
rare; on Windows GetSystemTimeAsFileTime() ticks at a millisecond or
coarser, so a burst of chunks, which is exactly what a 4KB pipe read
now produces, readily shares one timestamp.  That is the last gap in
Windows task logs after bca9fc1: a run of lines cut mid-line at the
same byte offset every run, because the page boundary always fell in
the same place.

Remember the last timestamp issued per nspawn and never issue one that
is not greater than it.  This also makes the stored order of a burst
deterministic.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
diff --git a/src/builder/b-nspawn.c b/src/builder/b-nspawn.c index e2d42a9..33a38dc 100644 --- a/src/builder/b-nspawn.c +++ b/src/builder/b-nspawn.c @@ -43,6 +43,7 @@ int saib_log_chunk_create(struct sai_nspawn *ns, void *buf, size_t len, int channel) { char lj[2600 + LWS_PRE]; + lws_usec_t us; int n = 0; if (!ns || !ns->spm) @@ -67,11 +68,23 @@ saib_log_chunk_create(struct sai_nspawn *ns, void *buf, size_t len, int channel) return 0; } } + /* + * The web pages a task's logs 50 rows at a time with a strictly + * greater-than timestamp cursor, so chunks sharing the timestamp of + * the last row on a page are never delivered. On Windows the clock + * ticks at a millisecond or coarser, so a burst of chunks readily + * shares one: issue strictly increasing timestamps per nspawn. + */ + us = lws_now_usecs(); + if (us <= ns->last_log_us) + us = ns->last_log_us + 1; + ns->last_log_us = us; + n = lws_snprintf(lj + LWS_PRE, sizeof(lj) - LWS_PRE, "{\"schema\":\"com-warmcat-sai-logs\"," "\"task_uuid\":\"%s\", \"timestamp\": %llu," "\"channel\": %d, \"len\": %d, ", - ns->task->uuid, (unsigned long long)lws_now_usecs(), + ns->task->uuid, (unsigned long long)us, channel, (int)len); if (ns->retcode_set) { diff --git a/src/common/include/private.h b/src/common/include/private.h index 6be9e7e..bf1d64e 100644 --- a/src/common/include/private.h +++ b/src/common/include/private.h @@ -266,6 +266,7 @@ struct sai_nspawn { sai_task_t *task; unsigned int log_count; + lws_usec_t last_log_us; /* last chunk timestamp issued */ unsigned int killed_for_spew:1; struct lws *stdwsi[3];
Page fetched 0s ago, creation time: 8ms (vhost etag hits: 0%, cache hits: 0%)