Skip to content

Commit 079c54c

Browse files
committed
refactor: remove SQL queries for sourcemaps and implement S3 storage listing functionality
1 parent 1806abd commit 079c54c

File tree

2 files changed

+42
-25
lines changed

2 files changed

+42
-25
lines changed

apps/backend/src/routes.rs

Lines changed: 10 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ use axum::extract::State;
44
use axum::http::StatusCode;
55
use axum::routing::{delete, get, post};
66
use serde::{Deserialize, Serialize};
7-
use sqlx::Row;
87
use tower_http::trace::TraceLayer;
98
use tracing::info;
109
use uuid::Uuid;
@@ -120,14 +119,6 @@ pub async fn ingest(
120119
let key = s3_key(project_id, &payload.build_id, &entry.file_name);
121120

122121
state.storage.put(&key, entry.sourcemap.as_bytes()).await?;
123-
124-
sqlx::query(
125-
"INSERT INTO source_maps (project_id, type, file, url, created_at) VALUES ($1, 'file', $2, NULL, NOW())",
126-
)
127-
.bind(project_id)
128-
.bind(&key)
129-
.execute(&state.db)
130-
.await?;
131122
}
132123

133124
let ingested = payload.sourcemaps.len();
@@ -166,13 +157,7 @@ pub async fn wipe(
166157
let prefix = format!("{project_id}/");
167158

168159
let deleted_files = state.storage.delete_prefix(&prefix).await?;
169-
170-
let result = sqlx::query("DELETE FROM source_maps WHERE project_id = $1")
171-
.bind(project_id)
172-
.execute(&state.db)
173-
.await?;
174-
175-
let deleted_rows = result.rows_affected();
160+
let deleted_rows = 0;
176161

177162
info!(%project_id, deleted_files, deleted_rows, "wiped all sourcemaps");
178163

@@ -187,22 +172,22 @@ pub async fn list_sourcemaps(
187172
auth: AdminAuthenticatedProject,
188173
State(state): State<SharedState>,
189174
) -> Result<Json<SourcemapListResponse>, AppError> {
190-
let rows =
191-
sqlx::query("SELECT file FROM source_maps WHERE project_id = $1 ORDER BY created_at DESC")
192-
.bind(auth.project_id)
193-
.fetch_all(&state.db)
194-
.await?;
195-
196-
let sourcemaps = rows
175+
let prefix = format!("{}/", auth.project_id);
176+
let keys = state.storage.list_prefix_keys(&prefix).await?;
177+
let mut sourcemaps: Vec<SourcemapListItem> = keys
197178
.into_iter()
198-
.filter_map(|row| {
199-
let key: String = row.get("file");
179+
.filter_map(|key| {
200180
parse_sourcemap_key(&key).map(|(build_id, file_name)| SourcemapListItem {
201181
build_id,
202182
file_name,
203183
})
204184
})
205185
.collect();
186+
sourcemaps.sort_by(|a, b| {
187+
b.build_id
188+
.cmp(&a.build_id)
189+
.then_with(|| b.file_name.cmp(&a.file_name))
190+
});
206191

207192
Ok(Json(SourcemapListResponse {
208193
ok: true,

apps/backend/src/storage.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,38 @@ impl Storage {
106106

107107
Ok(deleted)
108108
}
109+
110+
pub async fn list_prefix_keys(&self, prefix: &str) -> Result<Vec<String>, AppError> {
111+
let mut keys = Vec::new();
112+
let mut continuation_token: Option<String> = None;
113+
114+
loop {
115+
let mut req = self
116+
.client
117+
.list_objects_v2()
118+
.bucket(&self.bucket)
119+
.prefix(prefix);
120+
121+
if let Some(token) = &continuation_token {
122+
req = req.continuation_token(token);
123+
}
124+
125+
let resp = req.send().await.map_err(s3_error)?;
126+
127+
for object in resp.contents() {
128+
if let Some(key) = object.key() {
129+
keys.push(key.to_string());
130+
}
131+
}
132+
133+
if resp.is_truncated() != Some(true) {
134+
break;
135+
}
136+
continuation_token = resp.next_continuation_token().map(Into::into);
137+
}
138+
139+
Ok(keys)
140+
}
109141
}
110142

111143
fn zstd_compress(data: &[u8]) -> Result<Vec<u8>, AppError> {

0 commit comments

Comments
 (0)