Skip to main content

RegionHook

Trait RegionHook 

Source
pub trait RegionHook:
    Send
    + Sync
    + Debug {
    // Provided methods
    fn on_sst_files_written<'life0, 'life1, 'life2, 'life3, 'async_trait>(
        &'life0 self,
        region_id: RegionId,
        region_metadata: &'life1 RegionMetadataRef,
        files: &'life2 [SstFileInfo<'life3>],
    ) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>
       where Self: 'async_trait,
             'life0: 'async_trait,
             'life1: 'async_trait,
             'life2: 'async_trait,
             'life3: 'async_trait { ... }
    fn on_manifest_updated<'life0, 'life1, 'async_trait>(
        &'life0 self,
        region_id: RegionId,
        action_list: &'life1 RegionMetaActionList,
        manifest_version: ManifestVersion,
    ) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>
       where Self: 'async_trait,
             'life0: 'async_trait,
             'life1: 'async_trait { ... }
    fn on_region_opened<'life0, 'life1, 'async_trait>(
        &'life0 self,
        region_id: RegionId,
        region_metadata: &'life1 RegionMetadataRef,
    ) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>
       where Self: 'async_trait,
             'life0: 'async_trait,
             'life1: 'async_trait { ... }
    fn on_region_closed<'life0, 'life1, 'async_trait>(
        &'life0 self,
        region_id: RegionId,
        region_metadata: &'life1 RegionMetadataRef,
    ) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>
       where Self: 'async_trait,
             'life0: 'async_trait,
             'life1: 'async_trait { ... }
    fn on_region_dropped<'life0, 'life1, 'async_trait>(
        &'life0 self,
        region_id: RegionId,
        region_metadata: &'life1 RegionMetadataRef,
    ) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>
       where Self: 'async_trait,
             'life0: 'async_trait,
             'life1: 'async_trait { ... }
    fn on_region_files_removed<'life0, 'life1, 'async_trait>(
        &'life0 self,
        region_id: RegionId,
        region_metadata: &'life1 RegionMetadataRef,
    ) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>
       where Self: 'async_trait,
             'life0: 'async_trait,
             'life1: 'async_trait { ... }
    fn on_region_gc<'life0, 'life1, 'life2, 'life3, 'life4, 'async_trait>(
        &'life0 self,
        region_id: RegionId,
        region_metadata: Option<&'life1 RegionMetadataRef>,
        access_layer: &'life2 AccessLayerRef,
        info: &'life3 RegionGcInfo<'life4>,
    ) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>
       where Self: 'async_trait,
             'life0: 'async_trait,
             'life1: 'async_trait,
             'life2: 'async_trait,
             'life3: 'async_trait,
             'life4: 'async_trait { ... }
}
Expand description

Hook for observing region mutations in mito2.

Implementations can be registered via the Plugins system:

use std::sync::Arc;
use common_base::Plugins;
use mito2::engine::region_hook::{RegionHook, RegionHookRef};

plugins.insert(Arc::new(MyHook) as RegionHookRef);

Provided Methods§

Source

fn on_sst_files_written<'life0, 'life1, 'life2, 'life3, 'async_trait>( &'life0 self, region_id: RegionId, region_metadata: &'life1 RegionMetadataRef, files: &'life2 [SstFileInfo<'life3>], ) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait,

Called after SST data files are physically written, before manifest commit.

This fires only when mito2 itself writes SST files (flush and compaction). It does not fire when SST files are pre-written externally (bulk ingestion, copy region) or when only index files are written (async index build).

§Metadata availability

See SstFileInfo: file_meta is always complete, but the SstInfo footer and index output are empty on remote compaction. Hooks needing column statistics (e.g. an Iceberg manifest) must fetch the footer from object storage.

Source

fn on_manifest_updated<'life0, 'life1, 'async_trait>( &'life0 self, region_id: RegionId, action_list: &'life1 RegionMetaActionList, manifest_version: ManifestVersion, ) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Called after the region manifest is successfully committed to the live (normal) manifest directory.

Fires for: flush, compaction, region edit, copy region, alter, truncate, async index build, and apply-staging promote. Does not fire for writes to the staging manifest directory (enter staging, operations during staging, the intermediate apply-staging edit) — those are suppressed because their effects are accumulated and delivered in a single promote notification.

Does not fire for:

  • Manifest reads / follower sync (no write)
  • GC / checkpoint (internal bookkeeping)
  • Failed manifest updates
Source

fn on_region_opened<'life0, 'life1, 'async_trait>( &'life0 self, region_id: RegionId, region_metadata: &'life1 RegionMetadataRef, ) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Called once a region open or create succeeds, but before the region is registered in the engine’s active set (insert_region runs immediately afterwards).

Fires once when a region becomes active via a create or open request — the natural counterpart to on_region_closed / on_region_dropped. It does not fire for the compactor’s transient compaction regions (open_compaction_region), nor for the internal reopen performed during follower catch-up / leadership promotion.

On the create path it runs inline in the region worker loop; on the open path it runs inside the spawned open task (common_runtime::spawn_global), concurrently with the worker loop (after WAL replay, before the region is registered/acknowledged). Implementations must be fast and must not assume worker-loop-thread affinity or strict ordering against concurrent requests to other regions.

Source

fn on_region_closed<'life0, 'life1, 'async_trait>( &'life0 self, region_id: RegionId, region_metadata: &'life1 RegionMetadataRef, ) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Called after a region is closed via a close request.

The region is removed from the engine’s active set, but its data files, manifest, and WAL state are preserved; the region may be reopened later. Fires once per successful close, after the region’s background tasks (flush/compaction) have been stopped.

Fires for a region of any role (leader or follower) that is closed. Does not fire when a region is dropped (see on_region_dropped).

Runs inline in the region worker loop; implementations should be fast.

Source

fn on_region_dropped<'life0, 'life1, 'async_trait>( &'life0 self, region_id: RegionId, region_metadata: &'life1 RegionMetadataRef, ) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Called after a region is logically dropped (a drop request has been handled).

The region is removed from the active set and its WAL entries are marked obsolete. Its data files are not yet deleted — they are scheduled for asynchronous removal by the GC worker. Observe physical deletion via on_region_files_removed.

Runs inline in the region worker loop; implementations should be fast.

Source

fn on_region_files_removed<'life0, 'life1, 'async_trait>( &'life0 self, region_id: RegionId, region_metadata: &'life1 RegionMetadataRef, ) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Called after a dropped region’s data files are physically removed by the drop GC worker (the region directory has been deleted).

This is the terminal event in a region’s file lifecycle; no further callbacks fire for this region id afterwards. Fires only when the drop worker itself deletes the directory. When global GC is enabled and the region is a normal table region dropped with partial_drop, the directory is left for global reclamation and this hook is not fired by the drop worker.

Runs on a background task, outside the region worker loop.

Source

fn on_region_gc<'life0, 'life1, 'life2, 'life3, 'life4, 'async_trait>( &'life0 self, region_id: RegionId, region_metadata: Option<&'life1 RegionMetadataRef>, access_layer: &'life2 AccessLayerRef, info: &'life3 RegionGcInfo<'life4>, ) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait, 'life4: 'async_trait,

Called after the datanode’s global GC worker (LocalGcWorker) finishes a GC pass for a region — live regions (periodic GC) or dropped/repartitioned regions (the global reclamation path). Also fired by the offline cleanup path (handle_offline_cleanup_request, i.e. soft-drop PURGE) once the region directory has been removed. Lets extensions with sidecar files outside mito2’s region dir clean up residual files.

Always scoped to RegionGcInfo::removed_files: clean only sidecar artifacts for the files mito deleted this pass. On a RegionGcInfo::full_file_listing pass you may also reconcile sidecar-only orphans (e.g. detect a fully-reaped region by cross-checking the region dir against your own manifest). This callback never authorizes blind whole-directory removal — derive “fully reaped” from your own state so a stale mito snapshot can’t cause accidental deletion. RegionGcInfo::is_region_dropped is context, not authorization.

§Retry

Returning Err keeps the region un-acknowledged (need_retry_regions) for a future replay. Dropped/repartitioned: guaranteed — metasrv keeps the table_repart tombstone until Ok, so full-listing passes continue until cleanup finishes. Live: best-effort — not expedited through candidate selection, and a later full-listing pass may not reconstruct the same removed_files; treat live cleanup as opportunistic.

region_metadata is None for dropped regions; use region_id + access_layer. Idempotent.

§Execution context

On the global-GC path this runs on the background GC task, outside the region worker loop. The offline cleanup path (handle_offline_cleanup_request, reached by soft-drop PURGE) instead runs it inline in the region worker loop and propagates Err so the caller retries the (idempotent) cleanup. So — like on_region_closed / on_region_dropped — implementations must be fast and must not block indefinitely while awaited there: while the callback is pending, every subsequent DDL request for every region on that worker is blocked. Extension authors who wrote their hook against the “background GC task” contract must account for this second, latency-sensitive trigger.

The offline cleanup path fires this callback once the region directory is confirmed absent — including no-op purges where nothing was actually removed this call (a retry after the directory was already gone, or a region that never had files on this datanode, since remove_region_dir_for_full_drop returns Ok for an absent/empty prefix). RegionGcInfo::removed_files is empty in that case; do not interpret the call as “files were deleted in this call”. This is asymmetric with the GC path, which fires only when files were deleted or a full listing was performed.

Implementors§