Skip to content

Commit 98aae51

Browse files
committed
Add helper function to clean up sequences older than a given age in MongoDB store
1 parent f6015bb commit 98aae51

2 files changed

Lines changed: 53 additions & 2 deletions

File tree

crates/hotfix/src/store/error.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ pub enum StoreError {
3232
/// Failed to reset the store.
3333
#[error("failed to reset store")]
3434
Reset(#[source] BoxError),
35+
36+
/// Failed to cleanup old sequences.
37+
#[error("failed to cleanup old sequences")]
38+
Cleanup(#[source] BoxError),
3539
}
3640

3741
/// A specialized Result type for store operations.

crates/hotfix/src/store/mongodb.rs

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
use async_trait::async_trait;
2-
use chrono::{DateTime, Utc};
2+
use chrono::{DateTime, Duration, Utc};
33
use futures::TryStreamExt;
4-
use mongodb::bson::Binary;
54
use mongodb::bson::doc;
65
use mongodb::bson::oid::ObjectId;
76
use mongodb::bson::spec::BinarySubtype;
7+
use mongodb::bson::{Binary, DateTime as BsonDateTime};
88
use mongodb::options::{FindOneOptions, IndexOptions, ReplaceOptions};
99
use mongodb::{Collection, Database, IndexModel};
1010
use serde::{Deserialize, Serialize};
@@ -100,6 +100,53 @@ impl MongoDbMessageStore {
100100

101101
Ok(initial_meta)
102102
}
103+
104+
/// Deletes sequences older than the specified age, along with their associated messages.
105+
///
106+
/// Returns the number of deleted sequences.
107+
pub async fn cleanup_older_than(&self, age: Duration) -> Result<u64> {
108+
let cutoff = BsonDateTime::from_millis((Utc::now() - age).timestamp_millis());
109+
110+
// Find old sequence IDs (excluding current sequence)
111+
let filter = doc! {
112+
"meta": true,
113+
"creation_time": { "$lt": cutoff },
114+
"_id": { "$ne": self.current_sequence.object_id }
115+
};
116+
let mut cursor = self
117+
.meta_collection
118+
.find(filter)
119+
.await
120+
.map_err(|e| StoreError::Cleanup(e.into()))?;
121+
122+
let mut old_sequence_ids = Vec::new();
123+
while let Some(meta) = cursor
124+
.try_next()
125+
.await
126+
.map_err(|e| StoreError::Cleanup(e.into()))?
127+
{
128+
old_sequence_ids.push(meta.object_id);
129+
}
130+
131+
if old_sequence_ids.is_empty() {
132+
return Ok(0);
133+
}
134+
135+
// Delete messages first to avoid orphaned meta documents
136+
self.message_collection
137+
.delete_many(doc! { "sequence_id": { "$in": &old_sequence_ids } })
138+
.await
139+
.map_err(|e| StoreError::Cleanup(e.into()))?;
140+
141+
// Delete sequence metas
142+
let result = self
143+
.meta_collection
144+
.delete_many(doc! { "_id": { "$in": &old_sequence_ids } })
145+
.await
146+
.map_err(|e| StoreError::Cleanup(e.into()))?;
147+
148+
Ok(result.deleted_count)
149+
}
103150
}
104151

105152
#[async_trait]

0 commit comments

Comments
 (0)