feat: P2-2 apply_wal_entry — standby WAL replay with LSN advance and type guards

Upgrade apply_wal_entry() from P0 static no-op stub to the real public
standby replay path:

- Reject oversized payloads (> MAX_WAL_PAYLOAD_BYTES) with -EMSGSIZE
- Skip WAL_CHECKPOINT (100) entries silently — local-only markers, never
  replicated to standbys; current_lsn is NOT advanced on skip
- Skip unknown types (> WAL_ENTRY_TYPE_MAX) with WARN log and rc=0 for
  forward compatibility with WAL written by newer controller versions
- Advance current_lsn to hdr->lsn+1 and update last_crc under p->lock
  for all accepted known entries
- Gate restore_job()/worker_from_capnp() calls on p->cluster != NULL so
  unit tests work without a full cluster wired in
- Add NULL guard returning -EINVAL for missing p or hdr

Add public declaration in persist.h with forward-declare stubs for
restore_job/worker_from_capnp in persist.c (avoids heavy cluster.h chain).

Test suite: 5 new Unity tests in test_repl_apply.c covering all branches.
Weak stubs for restore_job/worker_from_capnp in the test file satisfy the
linker without linking job.c/worker.c's heavy dependency graph.
All 5 new tests pass; full controller suite green.
This commit is contained in:
Rongsong Shen 2026-05-07 16:38:20 +00:00
parent 8ef64a7ee7
commit abefc8a128
5 changed files with 275 additions and 7 deletions

View file

@ -167,6 +167,12 @@ int persist_queue_hook_fun(int type, int situation, int detail,
int persist_worker_hook_fun(int type, int situation, int detail,
void* cls, va_list ap);
/* Apply a single WAL entry to in-memory state (standby replay path).
* No hooks fire — hook system is empty on standbys until promotion.
* Returns 0 on success (including skip for checkpoint/unknown types),
* negative errno on error (oversized payload, NULL arguments). */
int apply_wal_entry(persist_t* p, const wal_entry_hdr_t* hdr, const void* payload);
/* GC retention predicates (P0-5a / P0-8 / P0-13) */
#include <stdbool.h>
#include "xce/types.h"