1+ use crate :: db:: durability:: DurabilityWorker ;
12use crate :: db:: MetricsRecorderQueue ;
23use crate :: error:: { DBError , DatabaseError , RestoreSnapshotError } ;
34use crate :: messages:: control_db:: HostType ;
@@ -10,10 +11,9 @@ use fs2::FileExt;
1011use log:: info;
1112use spacetimedb_commitlog:: repo:: OnNewSegmentFn ;
1213use spacetimedb_commitlog:: { self as commitlog, SizeOnDisk } ;
13- use spacetimedb_data_structures:: map:: IntSet ;
1414use spacetimedb_datastore:: db_metrics:: DB_METRICS ;
1515use spacetimedb_datastore:: error:: { DatastoreError , TableError , ViewError } ;
16- use spacetimedb_datastore:: execution_context:: { ReducerContext , Workload , WorkloadType } ;
16+ use spacetimedb_datastore:: execution_context:: { Workload , WorkloadType } ;
1717use spacetimedb_datastore:: locking_tx_datastore:: datastore:: TxMetrics ;
1818use spacetimedb_datastore:: locking_tx_datastore:: state_view:: {
1919 IterByColEqMutTx , IterByColRangeMutTx , IterMutTx , IterTx , StateView ,
@@ -103,7 +103,7 @@ pub struct RelationalDB {
103103 owner_identity : Identity ,
104104
105105 inner : Locking ,
106- durability : Option < Arc < Durability > > ,
106+ durability : Option < DurabilityWorker > ,
107107 snapshot_worker : Option < SnapshotWorker > ,
108108
109109 row_count_fn : RowCountFn ,
@@ -154,6 +154,7 @@ impl RelationalDB {
154154 Arc :: new ( EnumMap :: from_fn ( |ty| ExecutionCounters :: new ( & ty, & database_identity) ) ) ;
155155
156156 let ( durability, disk_size_fn, snapshot_worker) = Persistence :: unzip ( persistence) ;
157+ let durability = durability. map ( DurabilityWorker :: new) ;
157158
158159 Self {
159160 inner,
@@ -766,19 +767,21 @@ impl RelationalDB {
766767 }
767768
768769 #[ tracing:: instrument( level = "trace" , skip_all) ]
769- pub fn commit_tx ( & self , tx : MutTx ) -> Result < Option < ( TxOffset , TxData , TxMetrics , String ) > , DBError > {
770+ #[ allow( clippy:: type_complexity) ]
771+ pub fn commit_tx ( & self , tx : MutTx ) -> Result < Option < ( TxOffset , Arc < TxData > , TxMetrics , String ) > , DBError > {
770772 log:: trace!( "COMMIT MUT TX" ) ;
771773
772- // TODO: Never returns `None` -- should it?
773774 let reducer_context = tx. ctx . reducer_context ( ) . cloned ( ) ;
775+ // TODO: Never returns `None` -- should it?
774776 let Some ( ( tx_offset, tx_data, tx_metrics, reducer) ) = self . inner . commit_mut_tx ( tx) ? else {
775777 return Ok ( None ) ;
776778 } ;
777779
778780 self . maybe_do_snapshot ( & tx_data) ;
779781
782+ let tx_data = Arc :: new ( tx_data) ;
780783 if let Some ( durability) = & self . durability {
781- Self :: do_durability ( & * * durability, reducer_context . as_ref ( ) , & tx_data)
784+ durability. request_durability ( reducer_context , & tx_data) ;
782785 }
783786
784787 Ok ( Some ( ( tx_offset, tx_data, tx_metrics, reducer) ) )
@@ -789,7 +792,7 @@ impl RelationalDB {
789792 & self ,
790793 tx : MutTx ,
791794 workload : Workload ,
792- ) -> Result < Option < ( TxData , TxMetrics , Tx ) > , DBError > {
795+ ) -> Result < Option < ( Arc < TxData > , TxMetrics , Tx ) > , DBError > {
793796 log:: trace!( "COMMIT MUT TX" ) ;
794797
795798 let Some ( ( tx_data, tx_metrics, tx) ) = self . inner . commit_mut_tx_downgrade ( tx, workload) ? else {
@@ -798,82 +801,14 @@ impl RelationalDB {
798801
799802 self . maybe_do_snapshot ( & tx_data) ;
800803
804+ let tx_data = Arc :: new ( tx_data) ;
801805 if let Some ( durability) = & self . durability {
802- Self :: do_durability ( & * * durability, tx. ctx . reducer_context ( ) , & tx_data)
806+ durability. request_durability ( tx. ctx . reducer_context ( ) . cloned ( ) , & tx_data) ;
803807 }
804808
805809 Ok ( Some ( ( tx_data, tx_metrics, tx) ) )
806810 }
807811
808- /// If `(tx_data, ctx)` should be appended to the commitlog, do so.
809- ///
810- /// Note that by this stage,
811- /// [`spacetimedb_datastore::locking_tx_datastore::committed_state::tx_consumes_offset`]
812- /// has already decided based on the reducer and operations whether the transaction should be appended;
813- /// this method is responsible only for reading its decision out of the `tx_data`
814- /// and calling `durability.append_tx`.
815- fn do_durability ( durability : & Durability , reducer_context : Option < & ReducerContext > , tx_data : & TxData ) {
816- use commitlog:: payload:: {
817- txdata:: { Mutations , Ops } ,
818- Txdata ,
819- } ;
820-
821- let is_not_ephemeral_table = |table_id : & TableId | -> bool {
822- tx_data
823- . ephemeral_tables ( )
824- . map ( |etables| !etables. contains ( table_id) )
825- . unwrap_or ( true )
826- } ;
827-
828- if tx_data. tx_offset ( ) . is_some ( ) {
829- let inserts: Box < _ > = tx_data
830- . inserts ( )
831- // Skip ephemeral tables
832- . filter ( |( table_id, _) | is_not_ephemeral_table ( table_id) )
833- . map ( |( table_id, rowdata) | Ops {
834- table_id : * table_id,
835- rowdata : rowdata. clone ( ) ,
836- } )
837- . collect ( ) ;
838-
839- let truncates: IntSet < TableId > = tx_data. truncates ( ) . collect ( ) ;
840-
841- let deletes: Box < _ > = tx_data
842- . deletes ( )
843- . filter ( |( table_id, _) | is_not_ephemeral_table ( table_id) )
844- . map ( |( table_id, rowdata) | Ops {
845- table_id : * table_id,
846- rowdata : rowdata. clone ( ) ,
847- } )
848- // filter out deletes for tables that are truncated in the same transaction.
849- . filter ( |ops| !truncates. contains ( & ops. table_id ) )
850- . collect ( ) ;
851-
852- let truncates = truncates. into_iter ( ) . filter ( is_not_ephemeral_table) . collect ( ) ;
853-
854- let inputs = reducer_context. map ( |rcx| rcx. into ( ) ) ;
855-
856- let txdata = Txdata {
857- inputs,
858- outputs : None ,
859- mutations : Some ( Mutations {
860- inserts,
861- deletes,
862- truncates,
863- } ) ,
864- } ;
865-
866- // TODO: Should measure queuing time + actual write
867- durability. append_tx ( txdata) ;
868- } else {
869- debug_assert ! (
870- !tx_data. has_rows_or_connect_disconnect( reducer_context) ,
871- "tx_data has no rows but has connect/disconnect: `{:?}`" ,
872- reducer_context. map( |rcx| & rcx. name) ,
873- ) ;
874- }
875- }
876-
877812 /// Get the [`DurableOffset`] of this database, or `None` if this is an
878813 /// in-memory instance.
879814 pub fn durable_tx_offset ( & self ) -> Option < DurableOffset > {
@@ -1511,8 +1446,8 @@ impl RelationalDB {
15111446 }
15121447
15131448 /// Reports the metrics for `reducer`, using counters provided by `db`.
1514- pub fn report_mut_tx_metrics ( & self , reducer : String , metrics : TxMetrics , tx_data : Option < TxData > ) {
1515- self . report_tx_metrics ( reducer, tx_data. map ( Arc :: new ) , Some ( metrics) , None ) ;
1449+ pub fn report_mut_tx_metrics ( & self , reducer : String , metrics : TxMetrics , tx_data : Option < Arc < TxData > > ) {
1450+ self . report_tx_metrics ( reducer, tx_data, Some ( metrics) , None ) ;
15161451 }
15171452
15181453 /// Reports subscription metrics for `reducer`, using counters provided by `db`.
0 commit comments