Merge pull request #10072 from dolthub/macneale4-claude/branch-activity-disable

Optionally enable branch activity stats
This commit is contained in:
Neil Macneale IV
2025-11-12 17:57:29 -08:00
committed by GitHub
11 changed files with 89 additions and 14 deletions

View File

@@ -85,6 +85,7 @@ type SqlEngineConfig struct {
AutoGCController *sqle.AutoGCController
BinlogReplicaController binlogreplication.BinlogReplicaController
EventSchedulerStatus eventscheduler.SchedulerStatus
BranchActivityTracking bool
}
type SqlEngineConfigOption func(*SqlEngineConfig)
@@ -250,7 +251,7 @@ func NewSqlEngine(
engine.Analyzer.Catalog.StatsProvider = statsPro
branchActivityTracker := doltdb.NewBranchActivityTracker(ctx)
branchActivityTracker := doltdb.NewBranchActivityTracker(ctx, config.BranchActivityTracking)
engine.Analyzer.ExecBuilder = rowexec.NewOverrideBuilder(kvexec.Builder{})
sessFactory := doltSessionFactory(pro, statsPro, mrEnv.Config(), bcController, gcSafepointController, config.Autocommit, branchActivityTracker)

View File

@@ -42,6 +42,7 @@ type commandLineServerConfig struct {
cfgDir string
autoCommit bool
doltTransactionCommit bool
branchActivityTracking bool
maxConnections uint64
maxWaitConnections uint32
maxWaitConnsTimeout time.Duration
@@ -86,6 +87,7 @@ func DefaultCommandLineServerConfig() *commandLineServerConfig {
logLevel: servercfg.DefaultLogLevel,
logFormat: servercfg.DefaultLogFormat,
autoCommit: servercfg.DefaultAutoCommit,
branchActivityTracking: servercfg.DefaultBranchActivityTracking,
maxConnections: servercfg.DefaultMaxConnections,
maxWaitConnections: servercfg.DefaultMaxWaitConnections,
maxWaitConnsTimeout: servercfg.DefaultMaxWaitConnectionsTimeout,
@@ -282,6 +284,11 @@ func (cfg *commandLineServerConfig) DoltTransactionCommit() bool {
return cfg.doltTransactionCommit
}
// BranchActivityTracking enables or disables the tracking of branch activity for the dolt_branch_activity table. The default is false.
func (cfg *commandLineServerConfig) BranchActivityTracking() bool {
return cfg.branchActivityTracking
}
// MaxConnections returns the maximum number of simultaneous connections the server will allow. The default is 1
func (cfg *commandLineServerConfig) MaxConnections() uint64 {
return cfg.maxConnections

View File

@@ -245,6 +245,7 @@ func ConfigureServices(
ServerHost: cfg.ServerConfig.Host(),
Autocommit: cfg.ServerConfig.AutoCommit(),
DoltTransactionCommit: cfg.ServerConfig.DoltTransactionCommit(),
BranchActivityTracking: cfg.ServerConfig.BranchActivityTracking(),
JwksConfig: cfg.ServerConfig.JwksConfig(),
SystemVariables: cfg.ServerConfig.SystemVars(),
ClusterController: clusterController,

View File

@@ -72,15 +72,22 @@ type BranchActivityTracker struct {
writeTimes map[branchActivityKey]time.Time
systemStartTime time.Time
activityChan chan branchActivityEvent
trackingEnabled bool
}
// IsTrackingEnabled returns whether branch activity tracking is enabled
func (t *BranchActivityTracker) IsTrackingEnabled() bool {
return t.trackingEnabled
}
// NewBranchActivityTracker creates a new branch activity tracker instance
func NewBranchActivityTracker(ctx context.Context) *BranchActivityTracker {
func NewBranchActivityTracker(ctx context.Context, trackingEnabled bool) *BranchActivityTracker {
tracker := &BranchActivityTracker{
readTimes: make(map[branchActivityKey]time.Time),
writeTimes: make(map[branchActivityKey]time.Time),
systemStartTime: time.Now(),
activityChan: make(chan branchActivityEvent, 64),
trackingEnabled: trackingEnabled,
}
// Start background processor, we ignore the cancel function as the tracker doesn't have a lifecycle.
@@ -117,7 +124,7 @@ func (t *BranchActivityTracker) processEvents(ctx context.Context) {
// RecordReadEvent records when a branch is read/accessed
func (t *BranchActivityTracker) RecordReadEvent(ctx context.Context, database, branch string) {
if ignoreEvent(ctx, branch) {
if !t.trackingEnabled || ignoreEvent(ctx, branch) {
return
}
@@ -135,7 +142,7 @@ func (t *BranchActivityTracker) RecordReadEvent(ctx context.Context, database, b
// RecordWriteEvent records when a branch is written/updated
func (t *BranchActivityTracker) RecordWriteEvent(ctx context.Context, database, branch string) {
if ignoreEvent(ctx, branch) {
if !t.trackingEnabled || ignoreEvent(ctx, branch) {
return
}

View File

@@ -61,6 +61,7 @@ const (
DefaultAutoCommit = true
DefaultAutoGCBehaviorEnable = true
DefaultDoltTransactionCommit = false
DefaultBranchActivityTracking = false
DefaultMaxConnections = 1000
DefaultMaxWaitConnections = 50
DefaultMaxWaitConnectionsTimeout = 60 * time.Second
@@ -160,6 +161,8 @@ type ServerConfig interface {
// DoltTransactionCommit defines the value of the @@dolt_transaction_commit session variable that enables Dolt
// commits to be automatically created when a SQL transaction is committed.
DoltTransactionCommit() bool
// BranchActivityTracking enables or disables the tracking of branch activity for the dolt_branch_activity table
BranchActivityTracking() bool
// DataDir is the path to a directory to use as the data dir, both to create new databases and locate existing ones.
DataDir() string
// CfgDir is the path to a directory to use to store the dolt configuration files.
@@ -245,9 +248,10 @@ func defaultServerConfigYAML() *YAMLConfig {
MaxQueryLenInLogs: ptr(DefaultMaxLoggedQueryLen),
EncodeLoggedQuery: ptr(DefaultEncodeLoggedQuery),
BehaviorConfig: BehaviorYAMLConfig{
ReadOnly: ptr(DefaultReadOnly),
AutoCommit: ptr(DefaultAutoCommit),
DoltTransactionCommit: ptr(DefaultDoltTransactionCommit),
ReadOnly: ptr(DefaultReadOnly),
AutoCommit: ptr(DefaultAutoCommit),
DoltTransactionCommit: ptr(DefaultDoltTransactionCommit),
BranchActivityTracking: ptr(DefaultBranchActivityTracking),
AutoGCBehavior: &AutoGCBehaviorYAMLConfig{
Enable_: ptr(DefaultAutoGCBehaviorEnable),
ArchiveLevel_: ptr(DefaultCompressionLevel),
@@ -326,6 +330,7 @@ const (
LogFormatKey = "log_format"
AutoCommitKey = "autocommit"
DoltTransactionCommitKey = "dolt_transaction_commit"
BranchActivityTrackingKey = "branch_activity_tracking"
DataDirKey = "data_dir"
CfgDirKey = "cfg_dir"
MaxConnectionsKey = "max_connections"

View File

@@ -15,6 +15,7 @@ BehaviorConfig servercfg.BehaviorYAMLConfig 0.0.0 behavior,omitempty
-AutoGCBehavior *servercfg.AutoGCBehaviorYAMLConfig 1.50.0 auto_gc_behavior,omitempty
--Enable_ *bool 1.50.0 enable,omitempty
--ArchiveLevel_ *int 1.52.1 archive_level,omitempty
-BranchActivityTracking *bool TBD branch_activity_tracking,omitempty
UserConfig servercfg.UserYAMLConfig 0.0.0 user,omitempty
-Name *string 0.0.0 name,omitempty
-Password *string 0.0.0 password,omitempty

View File

@@ -68,6 +68,8 @@ type BehaviorYAMLConfig struct {
EventSchedulerStatus *string `yaml:"event_scheduler,omitempty" minver:"1.17.0"`
AutoGCBehavior *AutoGCBehaviorYAMLConfig `yaml:"auto_gc_behavior,omitempty" minver:"1.50.0"`
BranchActivityTracking *bool `yaml:"branch_activity_tracking,omitempty" minver:"TBD"`
}
// UserYAMLConfig contains server configuration regarding the user account clients must use to connect
@@ -202,6 +204,7 @@ func ServerConfigAsYAMLConfig(cfg ServerConfig) *YAMLConfig {
AutoCommit: ptr(cfg.AutoCommit()),
DisableClientMultiStatements: ptr(cfg.DisableClientMultiStatements()),
DoltTransactionCommit: ptr(cfg.DoltTransactionCommit()),
BranchActivityTracking: ptr(cfg.BranchActivityTracking()),
EventSchedulerStatus: ptr(cfg.EventSchedulerStatus()),
AutoGCBehavior: autoGCBehavior,
},
@@ -275,6 +278,7 @@ func ServerConfigSetValuesAsYAMLConfig(cfg ServerConfig) *YAMLConfig {
AutoCommit: zeroIf(ptr(cfg.AutoCommit()), !cfg.ValueSet(AutoCommitKey)),
DisableClientMultiStatements: zeroIf(ptr(cfg.DisableClientMultiStatements()), !cfg.ValueSet(DisableClientMultiStatementsKey)),
DoltTransactionCommit: zeroIf(ptr(cfg.DoltTransactionCommit()), !cfg.ValueSet(DoltTransactionCommitKey)),
BranchActivityTracking: zeroIf(ptr(cfg.BranchActivityTracking()), !cfg.ValueSet(BranchActivityTrackingKey)),
EventSchedulerStatus: zeroIf(ptr(cfg.EventSchedulerStatus()), !cfg.ValueSet(EventSchedulerKey)),
},
ListenerConfig: ListenerYAMLConfig{
@@ -663,6 +667,15 @@ func (cfg YAMLConfig) DoltTransactionCommit() bool {
return *cfg.BehaviorConfig.DoltTransactionCommit
}
// BranchActivityTracking enables or disables the tracking of branch activity for the dolt_branch_activity table
func (cfg YAMLConfig) BranchActivityTracking() bool {
if cfg.BehaviorConfig.BranchActivityTracking == nil {
return DefaultBranchActivityTracking
}
return *cfg.BehaviorConfig.BranchActivityTracking
}
// LogLevel returns the level of logging that the server will use.
func (cfg YAMLConfig) LogLevel() LogLevel {
if cfg.LogLevelStr == nil {

View File

@@ -37,6 +37,7 @@ behavior:
auto_gc_behavior:
enable: true
archive_level: 1
branch_activity_tracking: false
listener:
host: localhost
@@ -89,6 +90,8 @@ jwks:
expected := ServerConfigAsYAMLConfig(DefaultServerConfig())
expected.BehaviorConfig.DoltTransactionCommit = &trueValue
falseValue := false
expected.BehaviorConfig.BranchActivityTracking = &falseValue
expected.CfgDirStr = nillableStrPtr("")
expected.PrivilegeFile = ptr("some other nonsense")
expected.BranchControlFile = ptr("third nonsense")

View File

@@ -76,6 +76,16 @@ type BranchActivityItr struct {
}
func NewBranchActivityItr(ctx *sql.Context, table *BranchActivityTable) (*BranchActivityItr, error) {
// Check if branch activity tracking is enabled
if provider, ok := ctx.Session.(doltdb.BranchActivityProvider); ok {
tracker := provider.GetBranchActivityTracker()
if tracker == nil || !tracker.IsTrackingEnabled() {
return nil, fmt.Errorf("branch activity tracking is not enabled; enable it in the server config with 'behavior.branch_activity_tracking: true'")
}
} else {
return nil, fmt.Errorf("branch activity tracking is not enabled; enable it in the server config with 'behavior.branch_activity_tracking: true'")
}
sessionCounts, err := countActiveSessions(ctx)
if err != nil {
return nil, err

View File

@@ -133,7 +133,7 @@ func newDoltHarness(t *testing.T) *DoltHarness {
t: t,
skippedQueries: defaultSkippedQueries,
parallelism: 1,
branchActivityTracker: doltdb.NewBranchActivityTracker(context.Background()),
branchActivityTracker: doltdb.NewBranchActivityTracker(context.Background(), true), // Default to enabled for tests
}
return dh

View File

@@ -4,7 +4,7 @@ load $BATS_TEST_DIRNAME/helper/query-server-common.bash
setup() {
setup_no_dolt_init
# Create first database
mkdir repo1
cd repo1
@@ -15,9 +15,9 @@ setup() {
dolt branch feature1
dolt branch feature2
dolt branch feature3
cd ../
# Create second database for multi-database testing
mkdir repo2
cd repo2
@@ -27,9 +27,22 @@ setup() {
dolt commit -Am "Initial commit"
dolt branch dev
dolt branch staging
cd ../
start_sql_server
# Define port and create complete config file
# Can't use start_sql_server_with_config because it hardcodes behavior.autocommit: false
# and we can't override it without duplicate YAML keys
PORT=$( definePORT )
cat > server.yaml <<EOF
listener:
port: $PORT
behavior:
branch_activity_tracking: true
EOF
start_sql_server_with_args_no_port "--config" "server.yaml"
}
teardown() {
@@ -119,7 +132,7 @@ start_idle_connection() {
# Same for repo2, should result in read on dev
dolt --use-db "repo2/dev" sql -q "SELECT SLEEP(60)" &
sleep 1
run dolt --use-db repo1 sql -q "SELECT branch FROM dolt_branch_activity WHERE last_read IS NOT NULL"
[ $status -eq 0 ]
[[ "$output" =~ "main" ]] || false
@@ -134,3 +147,17 @@ start_idle_connection() {
[[ ! "$output" =~ "staging" ]] || false # staging should have no activity
[[ ! "$output" =~ "feature1" ]] || false # feature1 should not appear (it's in repo1)
}
@test "branch-activity: error when tracking disabled" {
# Stop the server that has tracking enabled
stop_sql_server 1
# Start a new server without branch activity tracking (default config)
start_sql_server
cd repo1
# Attempt to query dolt_branch_activity should result in an error
run dolt sql -q "SELECT * FROM dolt_branch_activity"
[ $status -eq 1 ]
[[ "$output" =~ "branch activity tracking is not enabled" ]] || false
}