11import { ClusterConfig } from "../config/ClusterConfig" ;
22
3+ /**
4+ * Application command payload replicated through Raft log.
5+ */
36export interface Command {
7+ /** Command discriminator used by application state machine. */
48 type : string ;
9+ /** Command payload consumed by application state machine. */
510 payload : any ;
611}
712
13+ /**
14+ * Supported replicated log entry categories.
15+ */
816export enum LogEntryType {
917 COMMAND = 'COMMAND' ,
1018 CONFIG = 'CONFIG' ,
1119 NOOP = 'NOOP'
1220}
1321
22+ /**
23+ * Replicated Raft log record.
24+ */
1425export interface LogEntry {
26+ /** Raft term when this entry was created. */
1527 term : number ;
28+ /** Monotonic log index. */
1629 index : number ;
30+ /** Entry semantic type. */
1731 type : LogEntryType ;
32+ /** Command payload for COMMAND entries. */
1833 command ?: Command ;
34+ /** Cluster config payload for CONFIG entries. */
1935 config ?: ClusterConfig
2036}
2137
38+ /**
39+ * Validates a single log entry shape and type-specific payload fields.
40+ *
41+ * @param entry Entry to validate.
42+ * @throws Error When entry shape is invalid.
43+ */
2244export function validateLogEntry ( entry : LogEntry ) : void {
2345 if ( ! Number . isInteger ( entry . term ) || entry . term < 0 ) {
2446 throw new Error ( `Invalid term: ${ entry . term } . Term must be a non-negative integer.` ) ;
@@ -51,6 +73,12 @@ export function validateLogEntry(entry: LogEntry): void {
5173 }
5274}
5375
76+ /**
77+ * Validates a complete log sequence for per-entry validity and monotonic ordering.
78+ *
79+ * @param log Log entries in index order.
80+ * @throws Error When sequence invariants are violated.
81+ */
5482export function validateLogSequence ( log : LogEntry [ ] ) : void {
5583 if ( log . length === 0 ) {
5684 return ;
@@ -74,6 +102,9 @@ export function validateLogSequence(log: LogEntry[]): void {
74102 }
75103}
76104
105+ /**
106+ * Deep-compares two command payloads for deterministic test assertions.
107+ */
77108export function commandsEqual ( cmd1 : Command , cmd2 : Command ) : boolean {
78109 if ( cmd1 . type !== cmd2 . type ) {
79110 return false ;
@@ -84,6 +115,9 @@ export function commandsEqual(cmd1: Command, cmd2: Command): boolean {
84115 return payload1 === payload2 ;
85116}
86117
118+ /**
119+ * Compares two log entries by metadata and type-specific payload.
120+ */
87121export function entriesEqual ( entry1 : LogEntry , entry2 : LogEntry ) : boolean {
88122 if ( entry1 . term !== entry2 . term || entry1 . index !== entry2 . index ) {
89123 return false ;
@@ -106,6 +140,9 @@ export function entriesEqual(entry1: LogEntry, entry2: LogEntry): boolean {
106140 return commandsEqual ( entry1 . command ! , entry2 . command ! ) ;
107141}
108142
143+ /**
144+ * Compares two logs entry-by-entry.
145+ */
109146export function logsEqual ( log1 : LogEntry [ ] , log2 : LogEntry [ ] ) : boolean {
110147 if ( log1 . length !== log2 . length ) {
111148 return false ;
0 commit comments