speckl/out/KafkaKRaft.ts
Scott Scoble 8b520284cb TS generator: fix #12 (5 expression patterns) + #11 (opaque record types)
#12: All 5 untranslated SpeckDL patterns now emit valid JS:
  - notIn → !.has(), old() → drop, union → Set spread,
    set diff → filter, append() → [...X, Y], length() → .length
  - ==/!= operator replacement fixed (word-boundary regression)
  - Postcondition object comparisons get @ts-expect-error TS2839

#11: Generator auto-detects opaque identifier types used in state
  variables and action params, emits 'type X = any' before class.
  - State properties use ! (non-null assertion) for strict mode

TigerBeetleLedger → tsc --noEmit = 0 errors. 37/37 tests pass.
2026-05-11 10:16:15 -07:00

59 lines
1.9 KiB
TypeScript

// Auto-generated by speckl-compile from KafkaKRaft
// DO NOT EDIT MANUALLY — regenerate from .speckdl source
export const KafkaKRaftState = {
Candidate: 'candidate',
Leader: 'leader',
} as const;
export type KafkaKRaftState = typeof KafkaKRaftState[keyof typeof KafkaKRaftState];
export class KafkaKRaftMachine {
currentTerm: number;
state: KafkaKRaftState;
votedFor: Option(NodeId);
log: LogEntry[];
commitIndex: number;
nextIndex: Map<NodeId, number>;
matchIndex: Map<NodeId, number>;
votesGranted: Set<NodeId>;
decisionLog: any[] = [];
constructor() {
// No init block defined
}
RequestVote(candidate: NodeId, lastLogTerm: number, lastLogIndex: number) {
if (!(this.state == KafkaKRaftState.Candidate)) throw new Error('Guard failed: this.state == KafkaKRaftState.Candidate');
if (!(this.currentTerm >= lastLogTerm)) throw new Error('Guard failed: this.currentTerm >= lastLogTerm');
this.votesGranted = new Set([...this.votesGranted, candidate]);
}
HandleRequestVoteRequest(candidate: NodeId, candidateTerm: number, lastLogTerm: number, lastLogIndex: number) {
if (!(this.currentTerm >= candidateTerm)) throw new Error('Guard failed: this.currentTerm >= candidateTerm');
this.votedFor = Some(candidate);
}
BecomeLeader() {
if (!(this.state == KafkaKRaftState.Candidate)) throw new Error('Guard failed: this.state == KafkaKRaftState.Candidate');
if (!(this.votesGranted.size >= 3)) throw new Error('Guard failed: this.votesGranted.size >= 3');
this.state = KafkaKRaftState.Leader;
this.commitIndex = length(this.log);
}
AppendEntries(follower: NodeId) {
if (!(this.state == KafkaKRaftState.Leader)) throw new Error('Guard failed: this.state == KafkaKRaftState.Leader');
this.log = append(this.log, newEntry);
}
// V1: Always(TermMonotonicity)
async verify1(): Promise<boolean> {
// TODO: Model-check or monitor
// Temporal: Always(TermMonotonicity)
return true;
}
}