Conversation
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 5 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 7dbb16c. Configure here.
| .bind(id.as_storage_path()) | ||
| .bind(expires_at.map(|t| t.as_secs())) | ||
| .execute(&tx_db) | ||
| .await?; |
There was a problem hiding this comment.
Overwrites fail unique key constraint
High Severity
write always INSERTs into garbage_collector, but object_id is the primary key and the change stream uses write for overwrites. A second write of the same object hits a unique constraint, so the new expiration is dropped and the stale row remains.
Reviewed by Cursor Bugbot for commit 7dbb16c. Configure here.
|
|
||
| // Decrement counter when done | ||
| active_tasks.fetch_sub(1, Ordering::SeqCst); | ||
| }); |
There was a problem hiding this comment.
Unordered tasks lose object updates
High Severity
write, update, and delete each tokio::spawn an independent task with no per-object ordering. A later update or delete can commit before the matching write, so expirations are skipped and deleted objects can be reinserted.
Additional Locations (2)
Reviewed by Cursor Bugbot for commit 7dbb16c. Configure here.
| #[cfg(feature = "storage-cogs")] | ||
| mod cost_tracker; | ||
| mod factory; | ||
| mod garbage_collector_sqlite; |
There was a problem hiding this comment.
Collector is never constructed
Medium Severity
SqliteGarbageCollectorStream lives in a private module and is never re-exported or built by ChangeStreamFactory. No backend can select this collector, so the new feature is unreachable.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 7dbb16c. Configure here.
It's so hard to develop this on Windows. I need to grab my Linux laptop.
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #653 +/- ##
==========================================
+ Coverage 91.27% 91.33% +0.06%
==========================================
Files 116 117 +1
Lines 23496 23744 +248
==========================================
+ Hits 21445 21686 +241
- Misses 2051 2058 +7
☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
| // Write 3 records | ||
| stream.write(&id1, 1024, None); | ||
| stream.write(&id2, 2048, None); | ||
| stream.write(&id3, 4096, None); | ||
|
|
||
| // Update one | ||
| stream.update(&id2, Some(Timestamp::from_unix_secs(9999).unwrap())); | ||
|
|
||
| // Delete one | ||
| stream.delete(&id1); |
There was a problem hiding this comment.
Bug: Concurrent write and delete calls on the same object ID can race. The delete may execute before the write, leaving a phantom record in the garbage collector database.
Severity: HIGH
Suggested Fix
To prevent this race condition, ensure that operations on the same object_id are serialized. This could be achieved by using a mechanism like a sharded actor model or a keyed mutex, where each object_id has its own lock or sequential queue. This would guarantee that operations for a specific ID are executed in the order they were submitted, while still allowing for concurrency across different IDs.
Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.
Location: objectstore-service/src/change_stream/garbage_collector_sqlite.rs#L329-L338
Potential issue: The `write()`, `update()`, and `delete()` methods use `tokio::spawn` to
execute database operations asynchronously without awaiting their completion. This
creates a race condition where operations on the same `object_id` can execute out of
order. For example, a `delete()` call could run before a preceding `write()` call for
the same ID. This would cause the `DELETE` to affect zero rows, and the subsequent
`INSERT` would succeed, leaving a phantom record in the garbage collector database that
should have been removed. This leads to incorrect garbage collection behavior and silent
data consistency issues.


Supersedes #582