Skip to content

Commit 3e3302b

Browse files
Preslav LeConvex, Inc.
Preslav Le
authored and
Convex, Inc.
committed
Set retention_running before starting retention in IndexWorker (#24076)
Allow retention worker to process the backfilled index while we are caching up on retention. GitOrigin-RevId: 25a5e0eafc64e8391d0504abc8df7d7afbad41ff
1 parent 0e01a7c commit 3e3302b

File tree

1 file changed

+64
-35
lines changed

1 file changed

+64
-35
lines changed

Diff for: crates/database/src/index_worker.rs

+64-35
Original file line numberDiff line numberDiff line change
@@ -343,28 +343,41 @@ impl<RT: Runtime> IndexWorker<RT> {
343343
index_documents.values(),
344344
self.persistence_version,
345345
)?;
346-
let index_name = self.begin_backfill(index_id).await?;
347-
let index_selector = IndexSelector::Index {
348-
name: index_name,
349-
id: index_id,
350-
};
351-
self.index_writer
352-
.perform_backfill(
353-
self.database.now_ts_for_reads(),
354-
&index_registry,
355-
index_selector,
356-
)
357-
.await?;
346+
347+
// If retention is already started, we have already done with the initial
348+
// step of the backfill.
349+
let (index_name, retention_started) = self.begin_backfill(index_id).await?;
350+
if !retention_started {
351+
log::info!("Starting backfill of index {}", index_name);
352+
let index_selector = IndexSelector::Index {
353+
name: index_name,
354+
id: index_id,
355+
};
356+
self.index_writer
357+
.perform_backfill(
358+
self.database.now_ts_for_reads(),
359+
&index_registry,
360+
index_selector,
361+
)
362+
.await?;
363+
}
364+
365+
// Run retention.
358366
let (backfill_begin_ts, index_name, indexed_fields) =
359367
self.begin_retention(index_id).await?;
368+
log::info!("Started running retention for index {}", index_name);
360369
self.index_writer
361370
.run_retention(index_id, backfill_begin_ts, index_name, indexed_fields)
362371
.await?;
372+
363373
self.finish_backfill(index_id).await?;
364374
Ok(())
365375
}
366376

367-
async fn begin_backfill(&mut self, index_id: IndexId) -> anyhow::Result<TabletIndexName> {
377+
async fn begin_backfill(
378+
&mut self,
379+
index_id: IndexId,
380+
) -> anyhow::Result<(TabletIndexName, bool)> {
368381
let mut tx = self.database.begin(Identity::system()).await?;
369382
let index_table_id = tx.bootstrap_tables().index_id;
370383

@@ -382,21 +395,23 @@ impl<RT: Runtime> IndexWorker<RT> {
382395
// the state to still be `Backfilling` here. If this assertion fails, we
383396
// somehow raced with another `IndexWorker`(!) or don't actually have the
384397
// database lease (!).
385-
match &index_metadata.config {
386-
IndexConfig::Database { on_disk_state, .. } => anyhow::ensure!(
387-
matches!(*on_disk_state, DatabaseIndexState::Backfilling(_)),
388-
"IndexWorker started backfilling index {index_metadata:?} not in Backfilling state",
389-
),
398+
let retention_started = match &index_metadata.config {
399+
IndexConfig::Database { on_disk_state, .. } => {
400+
let DatabaseIndexState::Backfilling(state) = on_disk_state else {
401+
anyhow::bail!(
402+
"IndexWorker started backfilling index {index_metadata:?} not in \
403+
Backfilling state"
404+
);
405+
};
406+
state.retention_started
407+
},
390408
_ => anyhow::bail!(
391409
"IndexWorker attempted to backfill an index {index_metadata:?} which wasn't a \
392410
database index."
393411
),
394412
};
395413

396-
let ts = tx.begin_timestamp();
397-
drop(tx);
398-
log::info!("Starting backfill of index {} @ {ts}", index_metadata.name);
399-
Ok(index_metadata.name.clone())
414+
Ok((index_metadata.name.clone(), retention_started))
400415
}
401416

402417
async fn begin_retention(
@@ -410,34 +425,48 @@ impl<RT: Runtime> IndexWorker<RT> {
410425
.get_with_ts(ResolvedDocumentId::new(index_table_id, index_id))
411426
.await?
412427
.ok_or_else(|| anyhow::anyhow!("Index {index_id:?} no longer exists"))?;
413-
let index_metadata = TabletIndexMetadata::from_document(index_doc)?;
428+
let mut index_metadata = TabletIndexMetadata::from_document(index_doc)?;
414429

415430
// Assuming that the IndexWorker is the only writer of index state, we expect
416431
// the state to still be `Backfilling` here. If this assertion fails, we
417432
// somehow raced with another `IndexWorker`(!) or don't actually have the
418433
// database lease (!).
419-
let indexed_fields = match &index_metadata.config {
434+
let (index_ts, indexed_fields) = match &mut index_metadata.config {
420435
IndexConfig::Database {
421436
on_disk_state,
422437
developer_config,
423438
} => {
424-
anyhow::ensure!(
425-
matches!(*on_disk_state, DatabaseIndexState::Backfilling(_)),
426-
"IndexWorker started backfilling index {index_metadata:?} not in Backfilling \
427-
state",
428-
);
429-
developer_config.fields.clone()
439+
let DatabaseIndexState::Backfilling(state) = on_disk_state else {
440+
anyhow::bail!(
441+
"IndexWorker started backfilling index {index_metadata:?} not in \
442+
Backfilling state"
443+
)
444+
};
445+
446+
state.retention_started = true;
447+
448+
// TODO(presley): Remove the fallback to commit_ts.
449+
let WriteTimestamp::Committed(committed_ts) = index_ts else {
450+
anyhow::bail!("index {index_id} is pending write");
451+
};
452+
let index_created = state.index_created_lower_bound.unwrap_or(committed_ts);
453+
(index_created, developer_config.fields.clone())
430454
},
431455
_ => anyhow::bail!(
432456
"IndexWorker attempted to backfill an index {index_metadata:?} which wasn't a \
433457
database index."
434458
),
435459
};
436-
drop(tx);
437-
let WriteTimestamp::Committed(index_ts) = index_ts else {
438-
anyhow::bail!("index {index_id} is pending write");
439-
};
440-
Ok((index_ts, index_metadata.name.clone(), indexed_fields))
460+
461+
let name = index_metadata.name.clone();
462+
SystemMetadataModel::new(&mut tx)
463+
.replace(index_metadata.id(), index_metadata.into_value().try_into()?)
464+
.await?;
465+
self.database
466+
.commit_with_write_source(tx, "index_worker_start_retention")
467+
.await?;
468+
469+
Ok((index_ts, name, indexed_fields))
441470
}
442471

443472
async fn finish_backfill(&mut self, index_id: IndexId) -> anyhow::Result<()> {

0 commit comments

Comments
 (0)