From 9d8475e4f6ca3a8cbed35d92cf48a9192c783a1f Mon Sep 17 00:00:00 2001 From: Neil Macneale IV Date: Tue, 21 Oct 2025 17:31:46 -0700 Subject: [PATCH] Move read events to StartTransaction Also filter out event scheduler sessions --- go/cmd/dolt/commands/engine/sqlengine.go | 7 ++++- .../doltcore/doltdb/branch_activity.go | 29 ++++++++++++++----- go/libraries/doltcore/sqle/dsess/session.go | 20 +++++++++---- integration-tests/bats/branch-activity.bats | 17 +++++------ 4 files changed, 48 insertions(+), 25 deletions(-) diff --git a/go/cmd/dolt/commands/engine/sqlengine.go b/go/cmd/dolt/commands/engine/sqlengine.go index de83cc4c28..298966d9a1 100644 --- a/go/cmd/dolt/commands/engine/sqlengine.go +++ b/go/cmd/dolt/commands/engine/sqlengine.go @@ -20,6 +20,7 @@ import ( "strconv" "strings" + "github.com/dolthub/dolt/go/libraries/doltcore/doltdb" gms "github.com/dolthub/go-mysql-server" "github.com/dolthub/go-mysql-server/eventscheduler" "github.com/dolthub/go-mysql-server/sql" @@ -475,7 +476,11 @@ func configureEventScheduler(config *SqlEngineConfig, engine *gms.Engine, ctxFac if err != nil { return nil, err } - return ctxFactory(context.Background(), sql.WithSession(sess)), nil + + rootCtx := context.Background() + markedCtx := context.WithValue(rootCtx, doltdb.EventSessionContextKey, true) + + return ctxFactory(markedCtx, sql.WithSession(sess)), nil } // A hidden env var allows overriding the event scheduler period for testing. This option is not diff --git a/go/libraries/doltcore/doltdb/branch_activity.go b/go/libraries/doltcore/doltdb/branch_activity.go index 9ba93467ea..9a2af0d807 100644 --- a/go/libraries/doltcore/doltdb/branch_activity.go +++ b/go/libraries/doltcore/doltdb/branch_activity.go @@ -32,6 +32,12 @@ type statsSessionContextKeyType struct{} // reads/writes from these sessions in branch activity tracking. var StatsSessionContextKey = statsSessionContextKeyType{} +type eventSessionContextKeyType struct{} + +// EventSessionContextKey is used to mark sql sessions which are related to backround event. We don't want to count +// reads/writes from these sessions in branch activity tracking. +var EventSessionContextKey = eventSessionContextKeyType{} + // BranchActivityData represents activity data for a single branch type BranchActivityData struct { Branch string @@ -88,10 +94,7 @@ func BranchActivityInit(ctx context.Context) { // BranchActivityReadEvent records when a branch is read/accessed func BranchActivityReadEvent(ctx context.Context, branch string) { - if activityChan == nil { - return - } - if ctx.Value(StatsSessionContextKey) != nil { + if ignoreEvent(ctx) { return } @@ -108,10 +111,7 @@ func BranchActivityReadEvent(ctx context.Context, branch string) { // BranchActivityWriteEvent records when a branch is written/updated func BranchActivityWriteEvent(ctx context.Context, branch string) { - if activityChan == nil { - return - } - if ctx.Value(StatsSessionContextKey) != nil { + if ignoreEvent(ctx) { return } @@ -126,6 +126,19 @@ func BranchActivityWriteEvent(ctx context.Context, branch string) { } } +func ignoreEvent(ctx context.Context) bool { + if activityChan == nil { + return true + } + if ctx.Value(StatsSessionContextKey) != nil { + return true + } + if ctx.Value(EventSessionContextKey) != nil { + return true + } + return false +} + // GetBranchActivity returns activity data for all branches (tracked and untracked) func GetBranchActivity(ctx context.Context, ddb *DoltDB) ([]BranchActivityData, error) { if activityChan == nil { diff --git a/go/libraries/doltcore/sqle/dsess/session.go b/go/libraries/doltcore/sqle/dsess/session.go index e50ed0e8c7..18d6d9f903 100644 --- a/go/libraries/doltcore/sqle/dsess/session.go +++ b/go/libraries/doltcore/sqle/dsess/session.go @@ -181,11 +181,6 @@ func (d *DoltSession) lookupDbState(ctx *sql.Context, dbName string) (*branchSta if dbState.Err != nil { return nil, false, dbState.Err } - - // NM4 - record access time for branch activity table. - branchRef := ref.NewBranchRef(rev) - doltdb.BranchActivityReadEvent(ctx, branchRef.GetPath()) - return branchState, ok, nil } } @@ -431,6 +426,19 @@ func (d *DoltSession) StartTransaction(ctx *sql.Context, tCharacteristic sql.Tra _ = d.setDbSessionVars(ctx, bs, false) } + // Starting any transaction counts as a read of the given branch. We'll log that. NM4. + cdb := ctx.Session.GetCurrentDatabase() + _, rev := SplitRevisionDbName(cdb) + if rev != "" { + doltdb.BranchActivityReadEvent(ctx, rev) + } else { + rev, ok, err := d.CurrentHead(ctx, cdb) + if err == nil && ok { + doltdb.BranchActivityReadEvent(ctx, rev) + } + // Ignore errors here, we just won't log the read activity + } + return tx, nil } @@ -663,7 +671,7 @@ func (d *DoltSession) DoltCommit( return ws, commit, err } - + // NM4 - we may need to record branch activity write event here. return d.commitCurrentHead(ctx, dbName, tx, commitFunc) } diff --git a/integration-tests/bats/branch-activity.bats b/integration-tests/bats/branch-activity.bats index 941f45875b..ad2374926c 100644 --- a/integration-tests/bats/branch-activity.bats +++ b/integration-tests/bats/branch-activity.bats @@ -28,15 +28,14 @@ teardown() { # Helper function to start an idle dolt sql connection on a specific branch start_idle_connection() { local branch=$1 - + [ -n "$branch" ] || fail "Expected non-empty string, got empty" + # Do nothing connection to keep the branch activ - dolt sql --use-db "repo1/$branch" & + dolt --use-db "repo1/$branch" sql -q "SELECT SLEEP(60)" & local pid=$! # Store the PID for cleanup echo $pid >> $BATS_TMPDIR/idle_connections_$$ - - return $pid } # Helper function to cleanup idle connections @@ -60,11 +59,9 @@ cleanup_idle_connections() { sleep 1 # Now test that branch activity table shows the activity - run dolt sql -q "SELECT COUNT(*) FROM dolt_branch_activity WHERE last_read IS NOT NULL;" + run dolt sql -q "SELECT branch FROM dolt_branch_activity where last_read IS NOT NULL" [ $status -eq 0 ] - - # Should have at least some branches with read activity - run dolt sql -q "SELECT branch FROM dolt_branch_activity WHERE last_read IS NOT NULL ORDER BY branch;" - [ $status -eq 0 ] - + [[ "$output" =~ "main" ]] || false + [[ "$output" =~ "feature1" ]] || false + [[ "$output" =~ "feature2" ]] || false } \ No newline at end of file