@@ -147,6 +147,14 @@ pub async fn ingest(
147147 state. storage . put ( & key, entry. sourcemap . as_bytes ( ) ) . await ?;
148148 }
149149
150+ record_build_id (
151+ & state. db ,
152+ project_id,
153+ & payload. build_id ,
154+ & payload. uploaded_at ,
155+ )
156+ . await ?;
157+
150158 let ingested = payload. sourcemaps . len ( ) ;
151159 let total_bytes: usize = payload. sourcemaps . iter ( ) . map ( |e| e. sourcemap . len ( ) ) . sum ( ) ;
152160 let file_names: Vec < & str > = payload
@@ -175,6 +183,30 @@ pub async fn ingest(
175183 ) )
176184}
177185
186+ async fn record_build_id (
187+ db : & sqlx:: PgPool ,
188+ project_id : Uuid ,
189+ build_id : & str ,
190+ uploaded_at : & str ,
191+ ) -> Result < ( ) , AppError > {
192+ sqlx:: query (
193+ r#"
194+ INSERT INTO project_build_ids (project_id, build_id, deployed_at)
195+ VALUES ($1, $2, ($3::timestamptz AT TIME ZONE 'UTC'))
196+ ON CONFLICT (project_id, build_id)
197+ DO UPDATE SET deployed_at = EXCLUDED.deployed_at
198+ "# ,
199+ )
200+ . bind ( project_id)
201+ . bind ( build_id)
202+ . bind ( uploaded_at)
203+ . execute ( db)
204+ . await
205+ . map_err ( AppError :: Database ) ?;
206+
207+ Ok ( ( ) )
208+ }
209+
178210pub async fn wipe (
179211 auth : AdminAuthenticatedProject ,
180212 State ( state) : State < SharedState > ,
@@ -321,6 +353,7 @@ fn require_non_empty(field: &str, value: &str) -> Result<(), AppError> {
321353
322354fn validate_ingest_payload ( payload : & IngestPayload ) -> Result < ( ) , AppError > {
323355 require_non_empty ( "build_id" , & payload. build_id ) ?;
356+ require_non_empty ( "uploaded_at" , & payload. uploaded_at ) ?;
324357 if payload. sourcemaps . is_empty ( ) {
325358 return Err ( AppError :: BadRequest ( "no sourcemaps provided" . into ( ) ) ) ;
326359 }
0 commit comments