···3use crate::ops;
4use crate::resolver::ResolverError;
5use crate::state::AppState;
6+use crate::types::{
7+ AccountEvt, BroadcastEvent, GaugeState, RepoState, RepoStatus, ResyncState, StoredEvent,
8+};
910use fjall::Slice;
11use jacquard::api::com_atproto::sync::get_repo::{GetRepo, GetRepoError};
···237 Ok(previous_state) => {
238 let did_key = keys::repo_key(&did);
239240+ // determine old gauge state
241+ // if it was error/suspended etc, we need to know which error kind it was to decrement correctly.
242+ // we have to peek at the resync state. `previous_state` is the repo state, which tells us the Status.
243+ // we have to peek at the resync state. `previous_state` is the repo state, which tells us the Status.
244+ let old_gauge = match previous_state.status {
245+ RepoStatus::Backfilling => GaugeState::Pending,
246 RepoStatus::Error(_)
247+ | RepoStatus::Deactivated
248+ | RepoStatus::Takendown
249+ | RepoStatus::Suspended => {
250+ // we need to fetch the resync state to know the kind
251+ // if it's missing, we assume Generic (or handle gracefully)
252+ // this is an extra read, but necessary for accurate gauges.
253+ let resync_state = Db::get(db.resync.clone(), &did_key).await.ok().flatten();
254+ let kind = resync_state.and_then(|b| {
255+ rmp_serde::from_slice::<ResyncState>(&b)
256+ .ok()
257+ .and_then(|s| match s {
258+ ResyncState::Error { kind, .. } => Some(kind),
259+ _ => None,
260+ })
261+ });
262+ GaugeState::Resync(kind)
263+ }
264+ RepoStatus::Synced => GaugeState::Synced,
265+ };
266267 let mut batch = db.inner.batch();
268 // remove from pending
269+ if old_gauge == GaugeState::Pending {
270 batch.remove(&db.pending, pending_key);
271 }
272 // remove from resync
273+ if old_gauge.is_resync() {
274 batch.remove(&db.resync, &did_key);
275 }
276 tokio::task::spawn_blocking(move || batch.commit().into_diagnostic())
277 .await
278 .into_diagnostic()??;
279+280+ state
281+ .db
282+ .update_gauge_diff_async(&old_gauge, &GaugeState::Synced)
283+ .await;
0284285 let state = state.clone();
286 tokio::task::spawn_blocking(move || {
···368369 let mut batch = state.db.inner.batch();
370 batch.insert(&state.db.resync, &did_key, serialized_resync_state);
371+ batch.remove(&state.db.pending, pending_key.clone());
372 if let Some(state_bytes) = serialized_repo_state {
373 batch.insert(&state.db.repos, &did_key, state_bytes);
374 }
···378 .await
379 .into_diagnostic()??;
380381+ let old_gauge = if let Some(k) = prev_kind {
382+ GaugeState::Resync(Some(k))
383+ } else {
384+ GaugeState::Pending
385+ };
386+387+ let new_gauge = GaugeState::Resync(Some(error_kind));
388+389+ state
390+ .db
391+ .update_gauge_diff_async(&old_gauge, &new_gauge)
392+ .await;
39300000000000000000000000000000000000000000394 Err(e)
395 }
396 }