@@ -295,6 +295,8 @@ impl InstanceEnv {
295
295
if update_flags. is_scheduler_table {
296
296
self . schedule_row ( stdb, tx, table_id, row_ptr) ?;
297
297
}
298
+ tx. metrics . bytes_written += buffer. len ( ) ;
299
+ tx. metrics . rows_updated += 1 ;
298
300
299
301
Ok ( row_len)
300
302
}
@@ -490,14 +492,6 @@ impl From<GetTxError> for NodesError {
490
492
mod test {
491
493
use std:: { ops:: Bound , sync:: Arc } ;
492
494
493
- use anyhow:: { anyhow, Result } ;
494
- use parking_lot:: RwLock ;
495
- use spacetimedb_lib:: { bsatn:: to_vec, AlgebraicType , AlgebraicValue , Hash , Identity , ProductValue } ;
496
- use spacetimedb_paths:: { server:: ModuleLogsDir , FromPathUnchecked } ;
497
- use spacetimedb_primitives:: { IndexId , TableId } ;
498
- use spacetimedb_sats:: product;
499
- use tempfile:: TempDir ;
500
-
501
495
use crate :: {
502
496
database_logger:: DatabaseLogger ,
503
497
db:: {
@@ -512,6 +506,14 @@ mod test {
512
506
module_subscription_actor:: ModuleSubscriptions , module_subscription_manager:: SubscriptionManager ,
513
507
} ,
514
508
} ;
509
+ use anyhow:: { anyhow, Result } ;
510
+ use parking_lot:: RwLock ;
511
+ use spacetimedb_lib:: db:: auth:: StAccess ;
512
+ use spacetimedb_lib:: { bsatn:: to_vec, AlgebraicType , AlgebraicValue , Hash , Identity , ProductValue } ;
513
+ use spacetimedb_paths:: { server:: ModuleLogsDir , FromPathUnchecked } ;
514
+ use spacetimedb_primitives:: { IndexId , TableId } ;
515
+ use spacetimedb_sats:: product;
516
+ use tempfile:: TempDir ;
515
517
516
518
use super :: { ChunkPool , InstanceEnv , TxSlot } ;
517
519
@@ -622,6 +624,37 @@ mod test {
622
624
Ok ( ( table_id, index_id) )
623
625
}
624
626
627
+ fn create_table_with_unique_index ( db : & RelationalDB ) -> Result < ( TableId , IndexId ) > {
628
+ let table_id = db. create_table_for_test_with_the_works (
629
+ "t" ,
630
+ & [ ( "id" , AlgebraicType :: U64 ) , ( "str" , AlgebraicType :: String ) ] ,
631
+ & [ 0 . into ( ) ] ,
632
+ & [ 0 . into ( ) ] ,
633
+ StAccess :: Public ,
634
+ ) ?;
635
+ let index_id = db. with_read_only ( Workload :: ForTests , |tx| {
636
+ db. schema_for_table ( tx, table_id) ?
637
+ . indexes
638
+ . iter ( )
639
+ . find ( |schema| {
640
+ schema
641
+ . index_algorithm
642
+ . columns ( )
643
+ . as_singleton ( )
644
+ . is_some_and ( |col_id| col_id. idx ( ) == 0 )
645
+ } )
646
+ . map ( |schema| schema. index_id )
647
+ . ok_or_else ( || anyhow ! ( "Index not found for ColId `{}`" , 0 ) )
648
+ } ) ?;
649
+ db. with_auto_commit ( Workload :: ForTests , |tx| -> Result < _ > {
650
+ for i in 1 ..=5 {
651
+ db. insert ( tx, table_id, & bsatn_row ( i) ?) ?;
652
+ }
653
+ Ok ( ( ) )
654
+ } ) ?;
655
+ Ok ( ( table_id, index_id) )
656
+ }
657
+
625
658
#[ test]
626
659
fn table_scan_metrics ( ) -> Result < ( ) > {
627
660
let db = relational_db ( ) ?;
@@ -743,6 +776,33 @@ mod test {
743
776
Ok ( ( ) )
744
777
}
745
778
779
+ #[ test]
780
+ fn update_metrics ( ) -> Result < ( ) > {
781
+ let db = relational_db ( ) ?;
782
+ let env = instance_env ( db. clone ( ) ) ?;
783
+
784
+ let ( table_id, index_id) = create_table_with_unique_index ( & db) ?;
785
+
786
+ let mut tx_slot = env. tx . clone ( ) ;
787
+
788
+ let row_id: u64 = 1 ;
789
+ let row_val: String = "string" . to_string ( ) ;
790
+ let mut new_row_bytes = to_vec ( & product ! ( row_id, row_val) ) ?;
791
+ let new_row_len = new_row_bytes. len ( ) ;
792
+ // Delete a single row via the index
793
+ let f = || -> Result < _ > {
794
+ env. update ( table_id, index_id, new_row_bytes. as_mut_slice ( ) ) ?;
795
+ Ok ( ( ) )
796
+ } ;
797
+ let tx = db. begin_mut_tx ( IsolationLevel :: Serializable , Workload :: ForTests ) ;
798
+ let ( tx, res) = tx_slot. set ( tx, f) ;
799
+
800
+ res?;
801
+
802
+ assert_eq ! ( new_row_len, tx. metrics. bytes_written) ;
803
+ Ok ( ( ) )
804
+ }
805
+
746
806
#[ test]
747
807
fn delete_by_index_metrics ( ) -> Result < ( ) > {
748
808
let db = relational_db ( ) ?;
0 commit comments