Skip to content

Commit 3f651b7

Browse files
refactor(db): move git registry store ownership
Signed-off-by: tornquist <tornquist@squareup.com>
1 parent f87152c commit 3f651b7

3 files changed

Lines changed: 82 additions & 50 deletions

File tree

crates/buzz-db/src/git_repo.rs

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,11 @@
1616
//! idempotent re-announce (same owner) from a collision (different owner), and
1717
//! backs the per-pubkey quota via `COUNT`.
1818
19+
use buzz_datastore_tracing::datastore_span;
1920
use sqlx::{PgPool, Row as _};
2021

2122
use crate::error::Result;
22-
use crate::CommunityId;
23+
use crate::{CommunityId, Db};
2324

2425
/// Outcome of a name-reservation attempt.
2526
///
@@ -179,12 +180,62 @@ pub async fn release_repo_name(
179180
Ok(result.rows_affected())
180181
}
181182

183+
impl Db {
184+
/// Return the current owner of git repo name `repo_id` in `community`, or
185+
/// `None` if unreserved. See [`repo_name_owner`].
186+
#[datastore_span(name = "repo_name_owner", system = "postgresql")]
187+
pub async fn repo_name_owner(
188+
&self,
189+
community: CommunityId,
190+
repo_id: &str,
191+
) -> Result<Option<String>> {
192+
repo_name_owner(&self.pool, community, repo_id).await
193+
}
194+
195+
/// Reserve a git repo name for `owner_pubkey` in `community` (NIP-34).
196+
///
197+
/// See [`reserve_repo_name`] for the outcome semantics. The per-pubkey
198+
/// quota is enforced by the caller against `count_repos_for_owner`.
199+
#[datastore_span(name = "reserve_repo_name", system = "postgresql")]
200+
pub async fn reserve_repo_name(
201+
&self,
202+
community: CommunityId,
203+
repo_id: &str,
204+
owner_pubkey: &str,
205+
) -> Result<ReserveOutcome> {
206+
reserve_repo_name(&self.pool, community, repo_id, owner_pubkey).await
207+
}
208+
209+
/// Count git repos reserved by `owner_pubkey` in `community` (quota check).
210+
#[datastore_span(name = "count_repos_for_owner", system = "postgresql")]
211+
pub async fn count_repos_for_owner(
212+
&self,
213+
community: CommunityId,
214+
owner_pubkey: &str,
215+
) -> Result<i64> {
216+
count_repos_for_owner(&self.pool, community, owner_pubkey).await
217+
}
218+
219+
/// Release a git repo name reservation held by `owner_pubkey` (rollback).
220+
///
221+
/// Returns the number of rows removed (0 or 1). See [`release_repo_name`].
222+
#[datastore_span(name = "release_repo_name", system = "postgresql")]
223+
pub async fn release_repo_name(
224+
&self,
225+
community: CommunityId,
226+
repo_id: &str,
227+
owner_pubkey: &str,
228+
) -> Result<u64> {
229+
release_repo_name(&self.pool, community, repo_id, owner_pubkey).await
230+
}
231+
}
232+
182233
#[cfg(test)]
183234
mod tests {
184235
use super::*;
185236
use uuid::Uuid;
186237

187-
const TEST_DB_URL: &str = "postgres://buzz:buzz_dev@localhost:5432/buzz";
238+
const TEST_DB_URL: &str = "postgres://buzz:buzz_dev@localhost:5432/buzz"; // sadscan:disable np.postgres.1
188239

189240
async fn setup_pool() -> PgPool {
190241
let database_url = std::env::var("BUZZ_TEST_DATABASE_URL")

crates/buzz-db/src/lib.rs

Lines changed: 0 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1335,54 +1335,6 @@ impl Db {
13351335
Ok(result.rows_affected())
13361336
}
13371337

1338-
/// Return the current owner of git repo name `repo_id` in `community`, or
1339-
/// `None` if unreserved. See [`git_repo::repo_name_owner`].
1340-
#[datastore_span(name = "repo_name_owner", system = "postgresql")]
1341-
pub async fn repo_name_owner(
1342-
&self,
1343-
community: CommunityId,
1344-
repo_id: &str,
1345-
) -> Result<Option<String>> {
1346-
git_repo::repo_name_owner(&self.pool, community, repo_id).await
1347-
}
1348-
1349-
/// Reserve a git repo name for `owner_pubkey` in `community` (NIP-34).
1350-
///
1351-
/// See [`git_repo::reserve_repo_name`] for the outcome semantics. The
1352-
/// per-pubkey quota is enforced by the caller against `count_repos_for_owner`.
1353-
#[datastore_span(name = "reserve_repo_name", system = "postgresql")]
1354-
pub async fn reserve_repo_name(
1355-
&self,
1356-
community: CommunityId,
1357-
repo_id: &str,
1358-
owner_pubkey: &str,
1359-
) -> Result<git_repo::ReserveOutcome> {
1360-
git_repo::reserve_repo_name(&self.pool, community, repo_id, owner_pubkey).await
1361-
}
1362-
1363-
/// Count git repos reserved by `owner_pubkey` in `community` (quota check).
1364-
#[datastore_span(name = "count_repos_for_owner", system = "postgresql")]
1365-
pub async fn count_repos_for_owner(
1366-
&self,
1367-
community: CommunityId,
1368-
owner_pubkey: &str,
1369-
) -> Result<i64> {
1370-
git_repo::count_repos_for_owner(&self.pool, community, owner_pubkey).await
1371-
}
1372-
1373-
/// Release a git repo name reservation held by `owner_pubkey` (rollback).
1374-
///
1375-
/// Returns the number of rows removed (0 or 1). See [`git_repo::release_repo_name`].
1376-
#[datastore_span(name = "release_repo_name", system = "postgresql")]
1377-
pub async fn release_repo_name(
1378-
&self,
1379-
community: CommunityId,
1380-
repo_id: &str,
1381-
owner_pubkey: &str,
1382-
) -> Result<u64> {
1383-
git_repo::release_repo_name(&self.pool, community, repo_id, owner_pubkey).await
1384-
}
1385-
13861338
/// Returns `true` if `pubkey` (64-char hex) is archived in `community_id`.
13871339
#[datastore_span(name = "is_archived", system = "postgresql")]
13881340
pub async fn is_archived(&self, community_id: CommunityId, pubkey: &str) -> Result<bool> {

crates/buzz-db/tests/store_ownership.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1012,3 +1012,32 @@ fn workflow_lifecycle_store_has_single_ownership() {
10121012
assert_eq!(count(root, "pub async fn usage_workflow_counts("), 1);
10131013
assert_eq!(count(store, "pub async fn usage_workflow_counts("), 0);
10141014
}
1015+
1016+
#[test]
1017+
fn git_repo_store_has_single_ownership() {
1018+
let root = include_str!("../src/lib.rs");
1019+
let store = include_str!("../src/git_repo.rs");
1020+
1021+
for method in [
1022+
"repo_name_owner",
1023+
"reserve_repo_name",
1024+
"count_repos_for_owner",
1025+
"release_repo_name",
1026+
] {
1027+
let signature = format!("pub async fn {method}(");
1028+
assert_eq!(count(root, &signature), 0, "{method} remains in lib.rs");
1029+
assert_eq!(
1030+
count(store, &signature),
1031+
2,
1032+
"{method} must have one Db wrapper and one git registry SQL function"
1033+
);
1034+
assert_eq!(
1035+
count(store, &format!("name = \"{method}\"")),
1036+
1,
1037+
"{method} span is not unique"
1038+
);
1039+
}
1040+
1041+
assert_eq!(count(root, "enum ReserveOutcome"), 0);
1042+
assert_eq!(count(store, "enum ReserveOutcome"), 1);
1043+
}

0 commit comments

Comments
 (0)