Skip to content

Commit c68011b

Browse files
mzrfacebook-github-bot
authored andcommitted
add bundle-uri-cleaner to cleanup old bundles
Summary: We need something to cleanup old bundles. This is the thing that does it. There will be one task in tsp_global for it. Unsharded. Reviewed By: RajivTS Differential Revision: D75516918 fbshipit-source-id: a715cc0a51cf526b94881fa4b0fffa8b96d30d4c
1 parent 5615a3b commit c68011b

3 files changed

Lines changed: 194 additions & 0 deletions

File tree

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
load("@fbcode_macros//build_defs:rust_binary.bzl", "rust_binary")
2+
load("@fbcode_macros//build_defs/lib:rust_oss.bzl", "rust_oss")
3+
load("//fbpkg:fbpkg.bzl", "fbpkg")
4+
load("//tupperware/cm/antlir2/bzl:buck2_container.bzl", "tw")
5+
6+
oncall("scm_server_infra")
7+
8+
rust_binary(
9+
name = "git_bundle_cleaner",
10+
srcs = glob(["src/**/*.rs"]),
11+
named_deps = {
12+
"slog": "//common/rust/shed/tracing_slog_compat:tracing_slog_compat",
13+
} | ({} if rust_oss.is_oss_build() else {
14+
}),
15+
test_deps = [],
16+
deps = [
17+
"fbsource//third-party/rust:anyhow",
18+
"fbsource//third-party/rust:clap",
19+
"fbsource//third-party/rust:tokio",
20+
"//common/rust/shed/facet:facet",
21+
"//common/rust/shed/fbinit:fbinit",
22+
"//eden/mononoke/cmdlib/mononoke_app:mononoke_app",
23+
"//eden/mononoke/git/bundle_uri:bundle_uri",
24+
"//eden/mononoke/metaconfig:metaconfig_types",
25+
"//eden/mononoke/repo_attributes/repo_identity:repo_identity",
26+
"//manifold/clients/rust:manifold_client",
27+
],
28+
)
29+
30+
tw.container(
31+
name = "tw.mononoke.git_bundle_cleaner",
32+
features = [
33+
tw.build_fbpkg(
34+
fbpkg.builder(
35+
name = "mononoke.git_bundle_cleaner",
36+
path_actions = {
37+
"git_bundle_cleaner": ":git_bundle_cleaner",
38+
},
39+
),
40+
),
41+
],
42+
oncall = "scm_server_infra",
43+
)

eden/mononoke/git/bundle_uri/src/lib.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,12 @@ pub trait GitBundleUri: Send + Sync {
8686
/// There might be None.
8787
async fn get_latest_bundle_list(&self) -> Result<Option<BundleList>>;
8888

89+
/// Get all available bundle lists for a repo.
90+
async fn get_bundle_lists(&self) -> Result<Vec<BundleList>>;
91+
92+
/// Remove all bundles in a given bundle list from the metadata db.
93+
async fn remove_bundle_list_from_metadata_db(&self, bundle_list_num: u64) -> Result<()>;
94+
8995
async fn get_url_for_bundle_handle(
9096
&self,
9197
ctx: &CoreContext,
@@ -196,6 +202,16 @@ impl<U: Clone + Send + GitBundleUrlGenerator + Sync> GitBundleUri for BundleUri<
196202
self.bundle_metadata_storage.get_latest_bundle_list().await
197203
}
198204

205+
async fn get_bundle_lists(&self) -> Result<Vec<BundleList>> {
206+
self.bundle_metadata_storage.get_bundle_lists().await
207+
}
208+
209+
async fn remove_bundle_list_from_metadata_db(&self, bundle_list_num: u64) -> Result<()> {
210+
self.bundle_metadata_storage
211+
.remove_bundle_list(bundle_list_num)
212+
.await
213+
}
214+
199215
async fn add_new_bundles(&self, bundles: &[Bundle]) -> Result<u64> {
200216
self.bundle_metadata_storage.add_new_bundles(bundles).await
201217
}

eden/mononoke/git/bundle_uri/src/sql.rs

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,16 @@ mononoke_queries! {
3333
"
3434
}
3535

36+
read GetBundleListsForRepo(repo_id: RepositoryId) -> (
37+
String, u64, u64, String, u64
38+
) {
39+
"SELECT bundle_handle, in_bundle_list_order, bundle_list, bundle_fingerprint, generation_start_timestamp
40+
FROM git_bundles
41+
WHERE repo_id = {repo_id}
42+
ORDER BY bundle_list DESC, in_bundle_list_order ASC;
43+
"
44+
}
45+
3646
read GetLatestBundleListNumForRepo(repo_id: RepositoryId) -> (
3747
u64
3848
) {
@@ -65,6 +75,11 @@ mononoke_queries! {
6575
none,
6676
"INSERT INTO git_bundles (repo_id, bundle_handle, bundle_list, in_bundle_list_order, bundle_fingerprint, generation_start_timestamp) VALUES {values}"
6777
}
78+
79+
write RemoveBundleList(repo_id: RepositoryId, bundle_list: u64) {
80+
none,
81+
"DELETE FROM git_bundles WHERE repo_id = {repo_id} and bundle_list = {bundle_list}"
82+
}
6883
}
6984

7085
#[derive(Clone)]
@@ -173,6 +188,81 @@ impl SqlGitBundleMetadataStorage {
173188

174189
Ok(Some(bundle_list))
175190
}
191+
192+
pub async fn remove_bundle_list(&self, bundle_list_num: u64) -> Result<()> {
193+
RemoveBundleList::query(
194+
&self.connections.write_connection,
195+
&self.repo_id,
196+
&bundle_list_num,
197+
)
198+
.await?;
199+
Ok(())
200+
}
201+
202+
pub async fn get_bundle_lists(&self) -> Result<Vec<BundleList>> {
203+
let rows =
204+
GetBundleListsForRepo::query(&self.connections.read_connection, &self.repo_id).await?;
205+
206+
// +----------------------+-------------+
207+
// | in_bundle_list_order | bundle_list |
208+
// +----------------------+-------------+
209+
// | 1 | 3 |
210+
// | 1 | 2 |
211+
// | 2 | 2 |
212+
// | 3 | 2 |
213+
// | 1 | 1 |
214+
// +----------------------+-------------+
215+
let mut bundle_lists = vec![];
216+
let mut rows_iter = rows.into_iter().peekable();
217+
while let Some((
218+
handle,
219+
in_bundle_list_order,
220+
first_seen_bundle_list,
221+
fingerprint,
222+
generation_start_timestamp,
223+
)) = rows_iter.next()
224+
{
225+
let current_bundle_list_num = first_seen_bundle_list;
226+
// First bundle for a new bundle-list.
227+
let mut bundles = vec![Bundle {
228+
in_bundle_list_order,
229+
handle,
230+
fingerprint,
231+
generation_start_timestamp,
232+
}];
233+
234+
// Rest of the bundles for the new bundle-list.
235+
while let Some((
236+
handle,
237+
in_bundle_list_order,
238+
bundle_list,
239+
fingerprint,
240+
generation_start_timestamp,
241+
)) = rows_iter.peek()
242+
{
243+
if current_bundle_list_num == *bundle_list {
244+
// This bundle belongs to the current bundle-list.
245+
bundles.push(Bundle {
246+
in_bundle_list_order: *in_bundle_list_order,
247+
handle: handle.clone(),
248+
fingerprint: fingerprint.clone(),
249+
generation_start_timestamp: generation_start_timestamp.clone(),
250+
});
251+
rows_iter.next();
252+
} else {
253+
// This bundle is the first elem of the next bundle-list. Do not consume it.
254+
// Break the loop to finish processing current bundle.
255+
break;
256+
}
257+
}
258+
bundle_lists.push(BundleList {
259+
bundle_list_num: current_bundle_list_num,
260+
bundles,
261+
});
262+
}
263+
264+
Ok(bundle_lists)
265+
}
176266
}
177267

178268
#[cfg(test)]
@@ -277,4 +367,49 @@ mod test {
277367

278368
Ok(())
279369
}
370+
371+
#[mononoke::fbinit_test]
372+
async fn test_get_bundle_lists(_: FacebookInit) -> Result<()> {
373+
let repo_id = RepositoryId::new(2137);
374+
let storage = SqlGitBundleMetadataStorageBuilder::with_sqlite_in_memory()?.build(repo_id);
375+
376+
storage.add_new_bundles(&TEST_BUNDLE_LIST_2[..]).await?;
377+
storage.add_new_bundles(&TEST_BUNDLE_LIST_3[..]).await?;
378+
379+
let bundle_lists = storage.get_bundle_lists().await?;
380+
assert_eq!(bundle_lists.len(), 2);
381+
for bundle_list in bundle_lists.iter() {
382+
for (p, n) in bundle_list.bundles.iter().tuple_windows() {
383+
assert!(p.in_bundle_list_order < n.in_bundle_list_order)
384+
}
385+
}
386+
for (p, n) in bundle_lists.iter().tuple_windows() {
387+
assert!(p.bundle_list_num > n.bundle_list_num)
388+
}
389+
390+
Ok(())
391+
}
392+
393+
#[mononoke::fbinit_test]
394+
async fn test_remove_bundle_list(_: FacebookInit) -> Result<()> {
395+
let repo_id = RepositoryId::new(2137);
396+
let storage = SqlGitBundleMetadataStorageBuilder::with_sqlite_in_memory()?.build(repo_id);
397+
398+
let bundle_list_num_2 = storage.add_new_bundles(&TEST_BUNDLE_LIST_2[..]).await?;
399+
let bundle_list_num_3 = storage.add_new_bundles(&TEST_BUNDLE_LIST_3[..]).await?;
400+
401+
let bundle_lists = storage.get_bundle_lists().await?;
402+
assert_eq!(bundle_lists.len(), 2);
403+
assert_eq!(bundle_lists[0].bundle_list_num, bundle_list_num_3);
404+
assert_eq!(bundle_lists[1].bundle_list_num, bundle_list_num_2);
405+
storage.remove_bundle_list(bundle_list_num_2).await?;
406+
let bundle_lists = storage.get_bundle_lists().await?;
407+
assert_eq!(bundle_lists.len(), 1);
408+
assert_eq!(bundle_lists[0].bundle_list_num, bundle_list_num_3);
409+
storage.remove_bundle_list(bundle_list_num_3).await?;
410+
let bundle_lists = storage.get_bundle_lists().await?;
411+
assert_eq!(bundle_lists.len(), 0);
412+
413+
Ok(())
414+
}
280415
}

0 commit comments

Comments
 (0)