Skip to content

Commit 67d8678

Browse files
Copilotneongreen
andcommitted
tak: Persist Lamport timestamps across command runs
Bug fix: - Lamport timestamps were resetting to 1 on each command run - This caused all events to have ts=1, breaking proper claim resolution - When multiple status changes occurred, the reducer couldn't determine which was latest Solution: - Store Lamport counter in database metadata table - Increment and persist counter on each event creation - Load counter from DB instead of using global variable Changes: - Add DB.GetNextLamportTS() method to get/increment persisted counter - Remove global lamportCounter variable from ulid.go - Update all event creation in main.go to use DB method - Counter now properly increments: 1, 2, 3, 4, 5... Result: - Status updates now have increasing timestamps - Latest status correctly becomes effective - Older statuses marked as tentative - Proper conflict resolution based on both authority and timestamp Co-authored-by: neongreen <1523306+neongreen@users.noreply.github.com>
1 parent 1650169 commit 67d8678

4 files changed

Lines changed: 58 additions & 12 deletions

File tree

tak/db.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,43 @@ func (d *DB) GetOrCreateInstallationSuffix() (string, error) {
256256
return suffix, nil
257257
}
258258

259+
// GetNextLamportTS gets the next Lamport timestamp and increments the counter
260+
func (d *DB) GetNextLamportTS() (int64, error) {
261+
tx, err := d.db.Begin()
262+
if err != nil {
263+
return 0, fmt.Errorf("failed to begin transaction: %w", err)
264+
}
265+
defer tx.Rollback()
266+
267+
// Get current counter value
268+
var counter int64
269+
err = tx.QueryRow("SELECT value FROM metadata WHERE key = 'lamport_counter'").Scan(&counter)
270+
if err == sql.ErrNoRows {
271+
counter = 0
272+
} else if err != nil {
273+
return 0, fmt.Errorf("failed to query lamport counter: %w", err)
274+
}
275+
276+
// Increment counter
277+
nextTS := counter + 1
278+
279+
// Update or insert
280+
if counter == 0 {
281+
_, err = tx.Exec("INSERT INTO metadata (key, value) VALUES ('lamport_counter', ?)", nextTS)
282+
} else {
283+
_, err = tx.Exec("UPDATE metadata SET value = ? WHERE key = 'lamport_counter'", nextTS)
284+
}
285+
if err != nil {
286+
return 0, fmt.Errorf("failed to update lamport counter: %w", err)
287+
}
288+
289+
if err := tx.Commit(); err != nil {
290+
return 0, fmt.Errorf("failed to commit transaction: %w", err)
291+
}
292+
293+
return nextTS, nil
294+
}
295+
259296
// GetNextTaskNumber gets the next task number and increments the counter
260297
func (d *DB) GetNextTaskNumber() (int64, error) {
261298
tx, err := d.db.Begin()

tak/main.go

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,12 @@ var newCmd = &cobra.Command{
9393
}
9494
eventID := GenerateEventID()
9595

96+
// Get next Lamport timestamp from DB
97+
lamportTS, err := db.GetNextLamportTS()
98+
if err != nil {
99+
return err
100+
}
101+
96102
payload := TaskCreatedPayload{
97103
TaskID: taskID,
98104
Title: title,
@@ -106,7 +112,7 @@ var newCmd = &cobra.Command{
106112
now := time.Now()
107113
event := Event{
108114
ID: eventID,
109-
TS: GetNextLamportTS(),
115+
TS: lamportTS,
110116
CreatedAt: now,
111117
Actor: currentUser,
112118
Role: "human",
@@ -165,6 +171,12 @@ var statusSetCmd = &cobra.Command{
165171

166172
eventID := GenerateEventID()
167173

174+
// Get next Lamport timestamp from DB
175+
lamportTS, err := db.GetNextLamportTS()
176+
if err != nil {
177+
return err
178+
}
179+
168180
payload := TaskStatusSetPayload{
169181
TaskID: fullTaskID,
170182
Axis: axis,
@@ -179,7 +191,7 @@ var statusSetCmd = &cobra.Command{
179191
now := time.Now()
180192
event := Event{
181193
ID: eventID,
182-
TS: GetNextLamportTS(),
194+
TS: lamportTS,
183195
CreatedAt: now,
184196
Actor: currentUser,
185197
Role: role,
@@ -223,6 +235,12 @@ var noteCmd = &cobra.Command{
223235

224236
eventID := GenerateEventID()
225237

238+
// Get next Lamport timestamp from DB
239+
lamportTS, err := db.GetNextLamportTS()
240+
if err != nil {
241+
return err
242+
}
243+
226244
payload := TaskNoteAddPayload{
227245
TaskID: fullTaskID,
228246
Markdown: text,
@@ -235,7 +253,7 @@ var noteCmd = &cobra.Command{
235253
now := time.Now()
236254
event := Event{
237255
ID: eventID,
238-
TS: GetNextLamportTS(),
256+
TS: lamportTS,
239257
CreatedAt: now,
240258
Actor: currentUser,
241259
Role: "human",

tak/tak

6.08 KB
Binary file not shown.

tak/ulid.go

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,3 @@ func GenerateEventID() string {
3737
}
3838
return string(b)
3939
}
40-
41-
// Simple lamport timestamp counter
42-
var lamportCounter int64 = 0
43-
44-
// GetNextLamportTS returns the next Lamport timestamp
45-
func GetNextLamportTS() int64 {
46-
lamportCounter++
47-
return lamportCounter
48-
}

0 commit comments

Comments
 (0)