Skip to content

Commit eaefef5

Browse files
dobraccursoragent
authored andcommitted
feat(clickhouse): flag async_insert for sandbox host stats flushes
Co-authored-by: Cursor Agent <cursoragent@cursor.com> GitOrigin-RevId: cb1a9ba40f69575ba48a4c0155002777c3b449cd
1 parent 6617f24 commit eaefef5

3 files changed

Lines changed: 71 additions & 1 deletion

File tree

packages/clickhouse/pkg/hoststats/delivery.go

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"fmt"
66
"time"
77

8+
"github.com/ClickHouse/clickhouse-go/v2"
89
"github.com/ClickHouse/clickhouse-go/v2/lib/driver"
910
"go.opentelemetry.io/otel"
1011
"go.opentelemetry.io/otel/attribute"
@@ -43,6 +44,7 @@ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
4344
type ClickhouseDelivery struct {
4445
batcher *batcher.Batcher[SandboxHostStat]
4546
conn driver.Conn
47+
ff *featureflags.Client
4648
}
4749

4850
type GatedClickhouseDelivery struct {
@@ -75,6 +77,7 @@ func NewDefaultClickhouseHostStatsDelivery(
7577
logger.L().Error(ctx, "error batching sandbox host stats", zap.Error(err))
7678
},
7779
},
80+
featureFlags,
7881
)
7982
}
8083

@@ -86,8 +89,9 @@ func NewClickhouseHostStatsDelivery(
8689
ctx context.Context,
8790
conn driver.Conn,
8891
opts batcher.BatcherOptions,
92+
featureFlags *featureflags.Client,
8993
) (*ClickhouseDelivery, error) {
90-
delivery := &ClickhouseDelivery{conn: conn}
94+
delivery := &ClickhouseDelivery{conn: conn, ff: featureFlags}
9195

9296
var err error
9397
delivery.batcher, err = batcher.NewBatcher(delivery.batchInserter, opts)
@@ -119,11 +123,25 @@ func (c *ClickhouseDelivery) Close(_ context.Context) error {
119123
return c.batcher.Stop()
120124
}
121125

126+
// insertSettings returns the per-query ClickHouse settings for one flush, or
127+
// nil when the server defaults apply.
128+
func (c *ClickhouseDelivery) insertSettings(ctx context.Context) clickhouse.Settings {
129+
if c.ff == nil || !c.ff.BoolFlag(ctx, featureflags.ClickhouseHostStatsAsyncInsertFlag) {
130+
return nil
131+
}
132+
133+
return clickhouse.Settings{"async_insert": 1}
134+
}
135+
122136
func (c *ClickhouseDelivery) batchInserter(ctx context.Context, stats []SandboxHostStat) error {
123137
attrs := trace.WithAttributes(attribute.Int("batch.size", len(stats)))
124138
ctx, span := tracer.Start(ctx, "Flush host stats batch to Clickhouse", attrs)
125139
defer span.End()
126140

141+
if settings := c.insertSettings(ctx); settings != nil {
142+
ctx = clickhouse.Context(ctx, clickhouse.WithSettings(settings))
143+
}
144+
127145
batch, err := c.conn.PrepareBatch(ctx, InsertSandboxHostStatQuery, driver.WithReleaseConnection())
128146
if err != nil {
129147
span.RecordError(err)

packages/clickhouse/pkg/hoststats/delivery_test.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"testing"
66

7+
"github.com/ClickHouse/clickhouse-go/v2"
78
"github.com/launchdarkly/go-server-sdk/v7/testhelpers/ldtestdata"
89
"github.com/stretchr/testify/require"
910

@@ -59,3 +60,46 @@ func TestGatedClickhouseDelivery_PushNilFeatureFlagsDrops(t *testing.T) {
5960
err := d.Push(SandboxHostStat{})
6061
require.NoError(t, err)
6162
}
63+
64+
func setAsyncInsertFlag(t *testing.T, source *ldtestdata.TestDataSource, value bool) {
65+
t.Helper()
66+
67+
source.Update(source.Flag(featureflags.ClickhouseHostStatsAsyncInsertFlag.Key()).VariationForAll(value))
68+
}
69+
70+
func TestClickhouseDelivery_InsertSettingsFlagOnEnablesAsyncInsert(t *testing.T) {
71+
t.Parallel()
72+
73+
ff, source := newTestFeatureFlags(t)
74+
setAsyncInsertFlag(t, source, true)
75+
d := &ClickhouseDelivery{ff: ff}
76+
77+
require.Equal(t, clickhouse.Settings{"async_insert": 1}, d.insertSettings(t.Context()))
78+
}
79+
80+
func TestClickhouseDelivery_InsertSettingsFlagOffKeepsServerDefaults(t *testing.T) {
81+
t.Parallel()
82+
83+
ff, source := newTestFeatureFlags(t)
84+
setAsyncInsertFlag(t, source, false)
85+
d := &ClickhouseDelivery{ff: ff}
86+
87+
require.Nil(t, d.insertSettings(t.Context()))
88+
}
89+
90+
func TestClickhouseDelivery_InsertSettingsUnsetFlagKeepsServerDefaults(t *testing.T) {
91+
t.Parallel()
92+
93+
ff, _ := newTestFeatureFlags(t)
94+
d := &ClickhouseDelivery{ff: ff}
95+
96+
require.Nil(t, d.insertSettings(t.Context()), "flag must fall back to off so a deploy changes nothing until flipped")
97+
}
98+
99+
func TestClickhouseDelivery_InsertSettingsNilFeatureFlagsKeepsServerDefaults(t *testing.T) {
100+
t.Parallel()
101+
102+
d := &ClickhouseDelivery{ff: nil}
103+
104+
require.Nil(t, d.insertSettings(t.Context()))
105+
}

packages/shared/pkg/featureflags/flags.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -862,6 +862,14 @@ var (
862862
// ClickHouse endpoints (CLICKHOUSE_CONNECTION_STRINGS). Default DSN
863863
// is unaffected.
864864
ClickhouseWriteFanoutFlag = NewBoolFlag("clickhouse-write-fanout", false)
865+
866+
// ClickhouseHostStatsAsyncInsertFlag sets async_insert=1 on every
867+
// sandbox_host_stats flush. Each orchestrator flushes its own small batch,
868+
// so without it the server writes one tiny part per node per flush; with
869+
// it the server buffers those inserts and writes one part per buffer flush.
870+
// wait_for_async_insert stays at the server default, so a rejected flush
871+
// still fails the batch and reaches the error handler.
872+
ClickhouseHostStatsAsyncInsertFlag = NewBoolFlag("clickhouse-host-stats-async-insert", false)
865873
)
866874

867875
// LogsWriteConfigFlag controls where sandbox/external logs are written, so

0 commit comments

Comments
 (0)