-
Notifications
You must be signed in to change notification settings - Fork 11
chore: smarter loading scheme #696
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 4 commits
01f8114
8f3bce9
14388c6
d156635
e8e5556
2bd44e2
3070be2
fc17063
be1cb2b
22d112e
44f4dc9
c186f4c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -89,14 +89,16 @@ func GetAllWorkspaceIDs(ctx context.Context) ([]string, error) { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| type WorkspaceSnapshot struct { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| WorkspaceID string | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Path string | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Timestamp time.Time | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Partition int32 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| NumPartitions int32 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Offset int64 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const WORKSPACE_SNAPSHOT_SELECT_QUERY = ` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| SELECT path, timestamp, partition, num_partitions FROM workspace_snapshot WHERE workspace_id = $1 ORDER BY timestamp DESC LIMIT 1 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| SELECT workspace_id, path, timestamp, partition, num_partitions, offset FROM workspace_snapshot WHERE workspace_id = $1 ORDER BY timestamp DESC LIMIT 1 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| func GetWorkspaceSnapshot(ctx context.Context, workspaceID string) (*WorkspaceSnapshot, error) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -108,10 +110,12 @@ func GetWorkspaceSnapshot(ctx context.Context, workspaceID string) (*WorkspaceSn | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| workspaceSnapshot := &WorkspaceSnapshot{} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| err = db.QueryRow(ctx, WORKSPACE_SNAPSHOT_SELECT_QUERY, workspaceID).Scan( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| &workspaceSnapshot.WorkspaceID, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| &workspaceSnapshot.Path, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| &workspaceSnapshot.Timestamp, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| &workspaceSnapshot.Partition, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| &workspaceSnapshot.NumPartitions, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| &workspaceSnapshot.Offset, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err == pgx.ErrNoRows { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -122,19 +126,58 @@ func GetWorkspaceSnapshot(ctx context.Context, workspaceID string) (*WorkspaceSn | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return workspaceSnapshot, nil | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| func GetLatestWorkspaceSnapshots(ctx context.Context, workspaceIDs []string) (map[string]*WorkspaceSnapshot, error) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| db, err := GetDB(ctx) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return nil, err | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| defer db.Release() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const query = ` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| SELECT DISTINCT ON (workspace_id) workspace_id, path, timestamp, partition, num_partitions, offset | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| FROM workspace_snapshot | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| WHERE workspace_id = ANY($1) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ORDER BY workspace_id, timestamp DESC | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| rows, err := db.Query(ctx, query, workspaceIDs) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return nil, err | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| defer rows.Close() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| var snapshots []*WorkspaceSnapshot | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for rows.Next() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| var snapshot WorkspaceSnapshot | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| err := rows.Scan(&snapshot.WorkspaceID, &snapshot.Path, &snapshot.Timestamp, &snapshot.Partition, &snapshot.NumPartitions, &snapshot.Offset) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return nil, err | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| snapshots = append(snapshots, &snapshot) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err := rows.Err(); err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return nil, err | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| snapshotMap := make(map[string]*WorkspaceSnapshot) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for _, snapshot := range snapshots { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| snapshotMap[snapshot.WorkspaceID] = snapshot | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return snapshotMap, nil | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
139
to
180
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix DISTINCT ON ordering to prefer highest offset; add fast-path for empty input. Ordering by timestamp can return stale offsets; prefer offset DESC then timestamp. Apply this diff: -func GetLatestWorkspaceSnapshots(ctx context.Context, workspaceIDs []string) (map[string]*WorkspaceSnapshot, error) {
- db, err := GetDB(ctx)
+func GetLatestWorkspaceSnapshots(ctx context.Context, workspaceIDs []string) (map[string]*WorkspaceSnapshot, error) {
+ if len(workspaceIDs) == 0 {
+ return map[string]*WorkspaceSnapshot{}, nil
+ }
+ db, err := GetDB(ctx)
@@
- const query = `
- SELECT DISTINCT ON (workspace_id) workspace_id, path, timestamp, partition, num_partitions, offset
- FROM workspace_snapshot
- WHERE workspace_id = ANY($1)
- ORDER BY workspace_id, timestamp DESC
- `
+ const query = `
+ SELECT DISTINCT ON (workspace_id)
+ workspace_id, path, timestamp, partition, num_partitions, offset
+ FROM workspace_snapshot
+ WHERE workspace_id = ANY($1)
+ ORDER BY workspace_id, offset DESC, timestamp DESC
+ `📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const WORKSPACE_SNAPSHOT_INSERT_QUERY = ` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| INSERT INTO workspace_snapshot (workspace_id, path, timestamp, partition, num_partitions) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| VALUES ($1, $2, $3, $4, $5) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| INSERT INTO workspace_snapshot (workspace_id, path, timestamp, partition, num_partitions, offset) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| VALUES ($1, $2, $3, $4, $5, $6) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| func WriteWorkspaceSnapshot(ctx context.Context, workspaceID string, snapshot *WorkspaceSnapshot) error { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| func WriteWorkspaceSnapshot(ctx context.Context, snapshot *WorkspaceSnapshot) error { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| db, err := GetDB(ctx) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return err | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| defer db.Release() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| _, err = db.Exec(ctx, WORKSPACE_SNAPSHOT_INSERT_QUERY, workspaceID, snapshot.Path, snapshot.Timestamp, snapshot.Partition, snapshot.NumPartitions) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| _, err = db.Exec(ctx, WORKSPACE_SNAPSHOT_INSERT_QUERY, snapshot.WorkspaceID, snapshot.Path, snapshot.Timestamp, snapshot.Partition, snapshot.NumPartitions, snapshot.Offset) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return err | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,10 @@ | ||
| package kafka | ||
|
|
||
| import ( | ||
| "context" | ||
| "math" | ||
| "workspace-engine/pkg/db" | ||
|
|
||
coderabbitai[bot] marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| "github.com/charmbracelet/log" | ||
| "github.com/confluentinc/confluent-kafka-go/v2/kafka" | ||
| ) | ||
|
|
@@ -27,3 +31,41 @@ func createConsumer() (*kafka.Consumer, error) { | |
|
|
||
| return c, nil | ||
| } | ||
|
|
||
| func getEarliestOffset(snapshots map[string]*db.WorkspaceSnapshot) int64 { | ||
| beginning := int64(kafka.OffsetBeginning) | ||
| if len(snapshots) == 0 { | ||
| return beginning | ||
| } | ||
|
|
||
| earliestOffset := int64(math.MaxInt64) | ||
| for _, snapshot := range snapshots { | ||
| if snapshot.Offset < earliestOffset { | ||
| earliestOffset = snapshot.Offset | ||
| } | ||
| } | ||
| if earliestOffset == math.MaxInt64 { | ||
| return beginning | ||
| } | ||
| return earliestOffset | ||
| } | ||
coderabbitai[bot] marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| func setOffsets(ctx context.Context, consumer *kafka.Consumer, partitionWorkspaceMap map[int32][]string) { | ||
| for partition, workspaceIDs := range partitionWorkspaceMap { | ||
| snapshots, err := db.GetLatestWorkspaceSnapshots(ctx, workspaceIDs) | ||
| if err != nil { | ||
| log.Error("Failed to get latest workspace snapshots", "error", err) | ||
| continue | ||
| } | ||
|
|
||
| earliestOffset := getEarliestOffset(snapshots) | ||
| if err := consumer.Seek(kafka.TopicPartition{ | ||
| Topic: &Topic, | ||
| Partition: partition, | ||
| Offset: kafka.Offset(earliestOffset), | ||
| }, 0); err != nil { | ||
|
Comment on lines
65
to
74
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chainPotential off-by-one: seek to next offset after the latest processed snapshot. If snapshot.Offset represents the last processed message, you should seek to snapshot.Offset+1 (unless using a sentinel like OffsetBeginning). Suggested change: - earliestOffset := getEarliestOffset(snapshots)
- if err := consumer.Seek(kafka.TopicPartition{
+ earliestOffset := getEarliestOffset(snapshots)
+ effective := earliestOffset
+ if effective >= 0 {
+ effective = earliestOffset + 1
+ }
+ if err := consumer.Seek(kafka.TopicPartition{
Topic: &Topic,
Partition: partition,
- Offset: kafka.Offset(earliestOffset),
+ Offset: kafka.Offset(effective),
}, 0); err != nil {Please confirm the stored snapshot offset semantics (last applied vs next to consume). I can adjust the diff accordingly. I'll need to examine the codebase to verify the snapshot offset semantics. Let me gather information about how offsets are handled. Length of output: 846 🏁 Script executed: #!/bin/bash
# Search for getEarliestOffset function definition
rg -n "getEarliestOffset" apps/workspace-engine/pkg/kafka/Length of output: 217 🏁 Script executed: #!/bin/bash
# Search for snapshot struct/type definitions to understand offset semantics
rg -n -A5 "type.*[Ss]napshot" apps/workspace-engine/pkg/Length of output: 418 🏁 Script executed: #!/bin/bash
# Search for how snapshots are populated or created
rg -n "snapshot.*Offset\s*=" apps/workspace-engine/pkg/ -C3Length of output: 0 🏁 Script executed: #!/bin/bash
# Search for other Seek() calls to understand the pattern
rg -n "Seek\(" apps/workspace-engine/pkg/kafka/ -C2Length of output: 379 I need to examine the complete WorkspaceSnapshot struct definition and trace where the Offset field comes from. Length of output: 586 🏁 Script executed: #!/bin/bash
# Search for Offset usage on snapshot objects
rg -n "snapshot\.Offset" apps/workspace-engine/pkg/Length of output: 580 🏁 Script executed: #!/bin/bash
# View GetLatestWorkspaceSnapshots function implementation
rg -n -A30 "func.*GetLatestWorkspaceSnapshots" apps/workspace-engine/pkg/db/Length of output: 2359 🏁 Script executed: #!/bin/bash
# Check if Offset is defined as a method on WorkspaceSnapshot
rg -n "func.*\(.*\*?WorkspaceSnapshot\).*Offset" apps/workspace-engine/pkg/Length of output: 0 I need to understand what offset value is stored when a snapshot is created. Let me examine where snapshots are inserted and how the offset is set. Length of output: 0 🏁 Script executed: #!/bin/bash
# Find the constant for insert query
rg -n "WORKSPACE_SNAPSHOT_INSERT" apps/workspace-engine/pkg/db/workspaces.go -A2Length of output: 404 🏁 Script executed: #!/bin/bash
# Search for where snapshot offset is set before insertion
rg -n -B10 "snapshot\.Offset\s*=" apps/workspace-engine/pkg/ | head -50Length of output: 0 🏁 Script executed: #!/bin/bash
# Search for Kafka message processing to understand when snapshots are created
rg -n "WorkspaceSnapshot\{" apps/workspace-engine/pkg/ -C5Length of output: 1656 🏁 Script executed: #!/bin/bash
# Look for any comments or documentation about offset semantics
rg -n -i "offset.*process|offset.*commi|last.*message" apps/workspace-engine/pkg/kafka/ -C2Length of output: 2024 I need to verify the Length of output: 495 🏁 Script executed: #!/bin/bash
# Find where beginning constant is defined
rg -n "beginning\s*:=" apps/workspace-engine/pkg/kafka/consumer.go -B3 -A1Length of output: 161 🏁 Script executed: #!/bin/bash
# View the entire consumer.go file to understand context of setOffsets function
cat apps/workspace-engine/pkg/kafka/consumer.go | head -100Length of output: 1965 Fix off-by-one error: seek to next offset after last processed snapshot. Snapshot.Offset stores the offset of the last processed message (set from - earliestOffset := getEarliestOffset(snapshots)
- if err := consumer.Seek(kafka.TopicPartition{
+ earliestOffset := getEarliestOffset(snapshots)
+ effective := earliestOffset
+ if effective >= 0 {
+ effective = earliestOffset + 1
+ }
+ if err := consumer.Seek(kafka.TopicPartition{
Topic: &Topic,
Partition: partition,
- Offset: kafka.Offset(earliestOffset),
+ Offset: kafka.Offset(effective),
}, 0); err != nil {🤖 Prompt for AI Agents |
||
| log.Error("Failed to seek to earliest offset", "error", err) | ||
| continue | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -2,25 +2,30 @@ package kafka | |||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| import ( | ||||||||||||||||||||||||||||||||||||||||||||
| "context" | ||||||||||||||||||||||||||||||||||||||||||||
| "encoding/json" | ||||||||||||||||||||||||||||||||||||||||||||
| "fmt" | ||||||||||||||||||||||||||||||||||||||||||||
| "os" | ||||||||||||||||||||||||||||||||||||||||||||
| "strconv" | ||||||||||||||||||||||||||||||||||||||||||||
| "time" | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| "workspace-engine/pkg/db" | ||||||||||||||||||||||||||||||||||||||||||||
| "workspace-engine/pkg/events" | ||||||||||||||||||||||||||||||||||||||||||||
| eventHanlder "workspace-engine/pkg/events/handler" | ||||||||||||||||||||||||||||||||||||||||||||
| "workspace-engine/pkg/oapi" | ||||||||||||||||||||||||||||||||||||||||||||
| "workspace-engine/pkg/workspace" | ||||||||||||||||||||||||||||||||||||||||||||
| wskafka "workspace-engine/pkg/workspace/kafka" | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| "github.com/aws/smithy-go/ptr" | ||||||||||||||||||||||||||||||||||||||||||||
| "github.com/charmbracelet/log" | ||||||||||||||||||||||||||||||||||||||||||||
| "github.com/confluentinc/confluent-kafka-go/v2/kafka" | ||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| // Configuration variables loaded from environment | ||||||||||||||||||||||||||||||||||||||||||||
| var ( | ||||||||||||||||||||||||||||||||||||||||||||
| Topic = getEnv("KAFKA_TOPIC", "workspace-events") | ||||||||||||||||||||||||||||||||||||||||||||
| GroupID = getEnv("KAFKA_GROUP_ID", "workspace-engine") | ||||||||||||||||||||||||||||||||||||||||||||
| Brokers = getEnv("KAFKA_BROKERS", "localhost:9092") | ||||||||||||||||||||||||||||||||||||||||||||
| Topic = getEnv("KAFKA_TOPIC", "workspace-events") | ||||||||||||||||||||||||||||||||||||||||||||
| GroupID = getEnv("KAFKA_GROUP_ID", "workspace-engine") | ||||||||||||||||||||||||||||||||||||||||||||
| Brokers = getEnv("KAFKA_BROKERS", "localhost:9092") | ||||||||||||||||||||||||||||||||||||||||||||
| MinSnapshotDistance = getEnvInt("SNAPSHOT_DISTANCE_MINUTES", 60) | ||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| // getEnv retrieves an environment variable or returns a default value | ||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -32,6 +37,40 @@ func getEnv(varName string, defaultValue string) string { | |||||||||||||||||||||||||||||||||||||||||||
| return v | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| // getEnvInt retrieves an integer environment variable or returns a default value | ||||||||||||||||||||||||||||||||||||||||||||
| func getEnvInt(varName string, defaultValue int64) int64 { | ||||||||||||||||||||||||||||||||||||||||||||
| v := os.Getenv(varName) | ||||||||||||||||||||||||||||||||||||||||||||
| if v == "" { | ||||||||||||||||||||||||||||||||||||||||||||
| return defaultValue | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
| i, err := strconv.ParseInt(v, 10, 64) | ||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||
| log.Warn("Failed to parse environment variable as integer, using default", "var", varName, "value", v, "default", defaultValue) | ||||||||||||||||||||||||||||||||||||||||||||
| return defaultValue | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
| return i | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| func getLastSnapshot(ctx context.Context, msg *kafka.Message) (*db.WorkspaceSnapshot, error) { | ||||||||||||||||||||||||||||||||||||||||||||
| var rawEvent eventHanlder.RawEvent | ||||||||||||||||||||||||||||||||||||||||||||
| if err := json.Unmarshal(msg.Value, &rawEvent); err != nil { | ||||||||||||||||||||||||||||||||||||||||||||
| log.Error("Failed to unmarshal event", "error", err, "message", string(msg.Value)) | ||||||||||||||||||||||||||||||||||||||||||||
| return nil, fmt.Errorf("failed to unmarshal event: %w", err) | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| return db.GetWorkspaceSnapshot(ctx, rawEvent.WorkspaceID) | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+39
to
+47
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Don’t log full payloads on JSON errors. Logging string(msg.Value) risks PII leakage and noisy logs. func getLastSnapshot(ctx context.Context, msg *kafka.Message) (*db.WorkspaceSnapshot, error) {
- var rawEvent eventHanlder.RawEvent
+ var rawEvent eventHanlder.RawEvent
if err := json.Unmarshal(msg.Value, &rawEvent); err != nil {
- log.Error("Failed to unmarshal event", "error", err, "message", string(msg.Value))
+ log.Error("Failed to unmarshal event", "error", err,
+ "topic", *msg.TopicPartition.Topic,
+ "partition", msg.TopicPartition.Partition,
+ "offset", msg.TopicPartition.Offset)
return nil, fmt.Errorf("failed to unmarshal event: %w", err)
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| func getLastWorkspaceOffset(snapshot *db.WorkspaceSnapshot) int64 { | ||||||||||||||||||||||||||||||||||||||||||||
| beginning := int64(kafka.OffsetBeginning) | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| if snapshot == nil { | ||||||||||||||||||||||||||||||||||||||||||||
| return beginning | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| return snapshot.Offset | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+49
to
+57
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Guard against cross-partition/topology mismatches when using stored offsets. Using a stored offset from a different partition or topology can skip/duplicate processing. -func getLastWorkspaceOffset(snapshot *db.WorkspaceSnapshot) int64 {
+func getLastWorkspaceOffset(snapshot *db.WorkspaceSnapshot, currentPartition int32, currentNumPartitions int32) int64 {
beginning := int64(kafka.OffsetBeginning)
if snapshot == nil {
return beginning
}
- return snapshot.Offset
+ if snapshot.Partition != currentPartition || snapshot.NumPartitions != currentNumPartitions {
+ return beginning
+ }
+ return snapshot.Offset
}
@@
- lastWorkspaceOffset := getLastWorkspaceOffset(lastSnapshot)
+ lastWorkspaceOffset := getLastWorkspaceOffset(
+ lastSnapshot,
+ msg.TopicPartition.Partition,
+ numPartitions,
+ )Also applies to: 175-182 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| // RunConsumerWithWorkspaceLoader starts the Kafka consumer with workspace-based offset resume | ||||||||||||||||||||||||||||||||||||||||||||
| // | ||||||||||||||||||||||||||||||||||||||||||||
| // Flow: | ||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -83,11 +122,17 @@ func RunConsumer(ctx context.Context) error { | |||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
| log.Info("Partition assignment complete", "assigned", assignedPartitions) | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| allWorkspaceIDs, err := wskafka.GetAssignedWorkspaceIDs(ctx, assignedPartitions, numPartitions) | ||||||||||||||||||||||||||||||||||||||||||||
| partitionWorkspaceMap, err := wskafka.GetAssignedWorkspaceIDs(ctx, assignedPartitions, numPartitions) | ||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||
| return fmt.Errorf("failed to get assigned workspace IDs: %w", err) | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| // Flatten the map to get all workspace IDs | ||||||||||||||||||||||||||||||||||||||||||||
| var allWorkspaceIDs []string | ||||||||||||||||||||||||||||||||||||||||||||
| for _, workspaceIDs := range partitionWorkspaceMap { | ||||||||||||||||||||||||||||||||||||||||||||
| allWorkspaceIDs = append(allWorkspaceIDs, workspaceIDs...) | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| storage := workspace.NewFileStorage("./state") | ||||||||||||||||||||||||||||||||||||||||||||
| if workspace.IsGCSStorageEnabled() { | ||||||||||||||||||||||||||||||||||||||||||||
| storage, err = workspace.NewGCSStorageClient(ctx) | ||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -118,6 +163,8 @@ func RunConsumer(ctx context.Context) error { | |||||||||||||||||||||||||||||||||||||||||||
| // Start consuming messages | ||||||||||||||||||||||||||||||||||||||||||||
| handler := events.NewEventHandler() | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| setOffsets(ctx, consumer, partitionWorkspaceMap) | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| for { | ||||||||||||||||||||||||||||||||||||||||||||
| // Check for cancellation | ||||||||||||||||||||||||||||||||||||||||||||
| select { | ||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -134,21 +181,46 @@ func RunConsumer(ctx context.Context) error { | |||||||||||||||||||||||||||||||||||||||||||
| continue | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| ws, err := handler.ListenAndRoute(ctx, msg) | ||||||||||||||||||||||||||||||||||||||||||||
| lastSnapshot, err := getLastSnapshot(ctx, msg) | ||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||
| log.Error("Failed to route message", "error", err) | ||||||||||||||||||||||||||||||||||||||||||||
| log.Error("Failed to get last snapshot", "error", err) | ||||||||||||||||||||||||||||||||||||||||||||
| continue | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| snapshot := &db.WorkspaceSnapshot{ | ||||||||||||||||||||||||||||||||||||||||||||
| Path: fmt.Sprintf("%s.gob", ws.ID), | ||||||||||||||||||||||||||||||||||||||||||||
| Timestamp: msg.Timestamp, | ||||||||||||||||||||||||||||||||||||||||||||
| Partition: int32(msg.TopicPartition.Partition), | ||||||||||||||||||||||||||||||||||||||||||||
| NumPartitions: numPartitions, | ||||||||||||||||||||||||||||||||||||||||||||
| messageOffset := int64(msg.TopicPartition.Offset) | ||||||||||||||||||||||||||||||||||||||||||||
| lastCommittedOffset, err := getCommittedOffset(consumer, msg.TopicPartition.Partition) | ||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||
| log.Error("Failed to get committed offset", "error", err) | ||||||||||||||||||||||||||||||||||||||||||||
| continue | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
| lastWorkspaceOffset := getLastWorkspaceOffset(lastSnapshot) | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| offsetTracker := eventHanlder.OffsetTracker{ | ||||||||||||||||||||||||||||||||||||||||||||
| LastCommittedOffset: lastCommittedOffset, | ||||||||||||||||||||||||||||||||||||||||||||
| LastWorkspaceOffset: lastWorkspaceOffset, | ||||||||||||||||||||||||||||||||||||||||||||
| MessageOffset: messageOffset, | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| ws, err := handler.ListenAndRoute(ctx, msg, offsetTracker) | ||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||
| log.Error("Failed to route message", "error", err) | ||||||||||||||||||||||||||||||||||||||||||||
| continue | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| if err := workspace.Save(ctx, storage, ws, snapshot); err != nil { | ||||||||||||||||||||||||||||||||||||||||||||
| log.Error("Failed to save workspace", "workspaceID", ws.ID, "snapshotPath", snapshot.Path, "error", err) | ||||||||||||||||||||||||||||||||||||||||||||
| shouldSaveSnapshot := lastSnapshot == nil || lastSnapshot.Timestamp.Before(msg.Timestamp.Add(-time.Duration(MinSnapshotDistance)*time.Minute)) | ||||||||||||||||||||||||||||||||||||||||||||
| if shouldSaveSnapshot { | ||||||||||||||||||||||||||||||||||||||||||||
| snapshot := &db.WorkspaceSnapshot{ | ||||||||||||||||||||||||||||||||||||||||||||
| WorkspaceID: ws.ID, | ||||||||||||||||||||||||||||||||||||||||||||
| Path: fmt.Sprintf("%s.gob", ws.ID), | ||||||||||||||||||||||||||||||||||||||||||||
| Timestamp: msg.Timestamp, | ||||||||||||||||||||||||||||||||||||||||||||
| Partition: int32(msg.TopicPartition.Partition), | ||||||||||||||||||||||||||||||||||||||||||||
| Offset: int64(msg.TopicPartition.Offset), | ||||||||||||||||||||||||||||||||||||||||||||
| NumPartitions: numPartitions, | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| if err := workspace.Save(ctx, storage, ws, snapshot); err != nil { | ||||||||||||||||||||||||||||||||||||||||||||
| log.Error("Failed to save workspace", "workspaceID", ws.ID, "snapshotPath", snapshot.Path, "error", err) | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| // Commit offset to Kafka | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
Uh oh!
There was an error while loading. Please reload this page.