@@ -676,6 +676,92 @@ function tests.test_range_cost()
676676 print (" PASS: test_range_cost" )
677677end
678678
679+ function tests .test_commit_hook ()
680+ local ffi = require (" ffi" )
681+ local path = " ./test_db_commit_hook"
682+ cleanup_db (path )
683+
684+ local db = tidesdb .TidesDB .open (path )
685+ db :create_column_family (" test_cf" )
686+ local cf = db :get_column_family (" test_cf" )
687+
688+ -- Track hook invocations
689+ local hook_called = 0
690+ local hook_ops_count = 0
691+ local hook_seq = 0
692+ local hook_keys = {}
693+ local hook_had_delete = false
694+
695+ local hook = ffi .cast (" tidesdb_commit_hook_fn" , function (ops , num_ops , commit_seq , ctx )
696+ hook_called = hook_called + 1
697+ hook_ops_count = hook_ops_count + num_ops
698+ hook_seq = tonumber (commit_seq )
699+ for i = 0 , num_ops - 1 do
700+ local key = ffi .string (ops [i ].key , ops [i ].key_size )
701+ table.insert (hook_keys , key )
702+ if ops [i ].is_delete ~= 0 then
703+ hook_had_delete = true
704+ end
705+ end
706+ return 0
707+ end )
708+
709+ -- Set commit hook
710+ cf :set_commit_hook (hook , nil )
711+
712+ -- Write data (should trigger the hook)
713+ local txn = db :begin_txn ()
714+ txn :put (cf , " key1" , " value1" )
715+ txn :put (cf , " key2" , " value2" )
716+ txn :commit ()
717+ txn :free ()
718+
719+ assert_true (hook_called >= 1 , " commit hook should have been called" )
720+ assert_true (hook_ops_count >= 2 , " hook should have received at least 2 ops" )
721+ assert_true (hook_seq > 0 , " commit_seq should be > 0" )
722+
723+ -- Verify keys were captured
724+ local found_key1 = false
725+ local found_key2 = false
726+ for _ , k in ipairs (hook_keys ) do
727+ if k == " key1" then found_key1 = true end
728+ if k == " key2" then found_key2 = true end
729+ end
730+ assert_true (found_key1 , " hook should have received key1" )
731+ assert_true (found_key2 , " hook should have received key2" )
732+
733+ -- Test delete operation fires hook
734+ hook_had_delete = false
735+ local del_txn = db :begin_txn ()
736+ del_txn :delete (cf , " key1" )
737+ del_txn :commit ()
738+ del_txn :free ()
739+
740+ assert_true (hook_had_delete , " hook should have received a delete operation" )
741+
742+ -- Save hook_called count before clearing
743+ local calls_before_clear = hook_called
744+
745+ -- Clear commit hook
746+ cf :clear_commit_hook ()
747+
748+ -- Write more data (should NOT trigger the hook)
749+ local txn2 = db :begin_txn ()
750+ txn2 :put (cf , " key3" , " value3" )
751+ txn2 :commit ()
752+ txn2 :free ()
753+
754+ assert_eq (hook_called , calls_before_clear , " hook should not fire after clearing" )
755+
756+ -- Clean up the callback to prevent GC issues
757+ hook :free ()
758+
759+ db :drop_column_family (" test_cf" )
760+ db :close ()
761+ cleanup_db (path )
762+ print (" PASS: test_commit_hook" )
763+ end
764+
679765-- Run all tests
680766local function run_tests ()
681767 print (" Running TidesDB Lua tests..." )
0 commit comments