Skip to content

Commit 659cdf6

Browse files
authored
Merge pull request #2254 from authzed/follow-up-pg-heartbeat
follow ups to #2252
2 parents bee5840 + 23e8eb3 commit 659cdf6

File tree

9 files changed

+40
-26
lines changed

9 files changed

+40
-26
lines changed

internal/datastore/postgres/options.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ const (
7878
defaultExpirationDisabled = false
7979
// no follower delay by default, it should only be set if using read replicas
8080
defaultFollowerReadDelay = 0
81-
defaultRevisionHeartbeat = false
81+
defaultRevisionHeartbeat = true
8282
)
8383

8484
// Option provides the facility to configure how clients within the

internal/datastore/postgres/postgres.go

+18-10
Original file line numberDiff line numberDiff line change
@@ -312,14 +312,17 @@ func newPostgresDatastore(
312312
followerReadDelayNanos,
313313
)
314314

315-
revisionHeartbeatQuery := fmt.Sprintf(
316-
insertHeartBeatRevision,
317-
colXID,
318-
tableTransaction,
319-
colTimestamp,
320-
quantizationPeriodNanos,
321-
colSnapshot,
322-
)
315+
var revisionHeartbeatQuery string
316+
if config.revisionHeartbeatEnabled {
317+
revisionHeartbeatQuery = fmt.Sprintf(
318+
insertHeartBeatRevision,
319+
colXID,
320+
tableTransaction,
321+
colTimestamp,
322+
quantizationPeriodNanos,
323+
colSnapshot,
324+
)
325+
}
323326

324327
validTransactionQuery := fmt.Sprintf(
325328
queryValidTransaction,
@@ -732,6 +735,11 @@ func (pgd *pgDatastore) Features(ctx context.Context) (*datastore.Features, erro
732735
}
733736

734737
func (pgd *pgDatastore) OfflineFeatures() (*datastore.Features, error) {
738+
continuousCheckpointing := datastore.FeatureUnsupported
739+
if pgd.revisionHeartbeatQuery != "" {
740+
continuousCheckpointing = datastore.FeatureSupported
741+
}
742+
735743
if pgd.watchEnabled {
736744
return &datastore.Features{
737745
Watch: datastore.Feature{
@@ -741,7 +749,7 @@ func (pgd *pgDatastore) OfflineFeatures() (*datastore.Features, error) {
741749
Status: datastore.FeatureUnsupported,
742750
},
743751
ContinuousCheckpointing: datastore.Feature{
744-
Status: datastore.FeatureSupported,
752+
Status: continuousCheckpointing,
745753
},
746754
WatchEmitsImmediately: datastore.Feature{
747755
Status: datastore.FeatureUnsupported,
@@ -765,7 +773,7 @@ func (pgd *pgDatastore) OfflineFeatures() (*datastore.Features, error) {
765773
const defaultMaxHeartbeatLeaderJitterPercent = 10
766774

767775
func (pgd *pgDatastore) startRevisionHeartbeat(ctx context.Context) error {
768-
heartbeatDuration := time.Nanosecond * time.Duration(pgd.quantizationPeriodNanos)
776+
heartbeatDuration := max(time.Second, time.Nanosecond*time.Duration(pgd.quantizationPeriodNanos))
769777
log.Info().Stringer("interval", heartbeatDuration).Msg("starting revision heartbeat")
770778
tick := time.NewTicker(heartbeatDuration)
771779

internal/datastore/postgres/postgres_shared_test.go

+5
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ func testPostgresDatastore(t *testing.T, config postgresTestConfig) {
8989
WatchBufferLength(watchBufferLength),
9090
DebugAnalyzeBeforeStatistics(),
9191
MigrationPhase(config.migrationPhase),
92+
WithRevisionHeartbeat(false), // heartbeat revision messes with tests that assert over revisions
9293
)
9394
require.NoError(t, err)
9495
return ds
@@ -111,6 +112,7 @@ func testPostgresDatastore(t *testing.T, config postgresTestConfig) {
111112
WatchBufferLength(watchBufferLength),
112113
DebugAnalyzeBeforeStatistics(),
113114
MigrationPhase(config.migrationPhase),
115+
WithRevisionHeartbeat(false), // heartbeat revision messes with tests that assert over revisions
114116
)
115117
require.NoError(t, err)
116118
return ds
@@ -173,6 +175,7 @@ func testPostgresDatastore(t *testing.T, config postgresTestConfig) {
173175
GCInterval(veryLargeGCInterval),
174176
WatchBufferLength(50),
175177
MigrationPhase(config.migrationPhase),
178+
WithRevisionHeartbeat(false),
176179
))
177180

178181
t.Run("OverlappingRevisionWatch", createDatastoreTest(
@@ -297,6 +300,7 @@ func testPostgresDatastoreWithoutCommitTimestamps(t *testing.T, config postgresT
297300
GCInterval(veryLargeGCInterval),
298301
WatchBufferLength(watchBufferLength),
299302
DebugAnalyzeBeforeStatistics(),
303+
WithRevisionHeartbeat(false),
300304
)
301305
require.NoError(t, err)
302306
return ds
@@ -316,6 +320,7 @@ func testPostgresDatastoreWithoutCommitTimestamps(t *testing.T, config postgresT
316320
GCInterval(gcInterval),
317321
WatchBufferLength(watchBufferLength),
318322
DebugAnalyzeBeforeStatistics(),
323+
WithRevisionHeartbeat(false),
319324
)
320325
require.NoError(t, err)
321326
return ds

internal/datastore/postgres/postgres_test.go

+1
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ func TestPostgresDatastoreGC(t *testing.T) {
7575
GCInterval(veryLargeGCInterval),
7676
WatchBufferLength(1),
7777
MigrationPhase(config.migrationPhase),
78+
WithRevisionHeartbeat(false),
7879
))
7980
})
8081
}

pkg/cmd/datastore/datastore.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ type Config struct {
174174
// Expermimental
175175
ExperimentalColumnOptimization bool `debugmap:"visible"`
176176
EnableExperimentalRelationshipExpiration bool `debugmap:"visible"`
177-
EnableExperimentalRevisionHeartbeat bool `debugmap:"visible"`
177+
EnableRevisionHeartbeat bool `debugmap:"visible"`
178178
}
179179

180180
//go:generate go run github.com/ecordell/optgen -sensitive-field-name-matches uri,secure -output zz_generated.relintegritykey.options.go . RelIntegrityKey
@@ -628,7 +628,7 @@ func newPostgresPrimaryDatastore(ctx context.Context, opts Config) (datastore.Da
628628
postgres.WatchBufferWriteTimeout(opts.WatchBufferWriteTimeout),
629629
postgres.MigrationPhase(opts.MigrationPhase),
630630
postgres.AllowedMigrations(opts.AllowedMigrations),
631-
postgres.WithRevisionHeartbeat(opts.EnableExperimentalRevisionHeartbeat),
631+
postgres.WithRevisionHeartbeat(opts.EnableRevisionHeartbeat),
632632
}
633633

634634
commonOptions, err := commonPostgresDatastoreOptions(opts)

pkg/cmd/datastore/zz_generated.options.go

+5-5
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/cmd/serve.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ func RegisterServeFlags(cmd *cobra.Command, config *server.Config) error {
112112
apiFlags.Uint32Var(&config.MaxDeleteRelationshipsLimit, "max-delete-relationships-limit", 1000, "maximum number of relationships that can be deleted in a single request")
113113
apiFlags.Uint32Var(&config.MaxLookupResourcesLimit, "max-lookup-resources-limit", 1000, "maximum number of resources that can be looked up in a single request")
114114
apiFlags.Uint32Var(&config.MaxBulkExportRelationshipsLimit, "max-bulk-export-relationships-limit", 10_000, "maximum number of relationships that can be exported in a single request")
115+
apiFlags.BoolVar(&config.EnableRevisionHeartbeat, "enable-revision-heartbeat", true, "enables support for revision heartbeat, used to create a synthetic revision on an interval defined by the quantization window (postgres only)")
115116

116117
datastoreFlags := nfs.FlagSet(BoldBlue("Datastore"))
117118
// Flags for the datastore
@@ -169,7 +170,6 @@ func RegisterServeFlags(cmd *cobra.Command, config *server.Config) error {
169170
Msg("The old implementation of LookupResources is no longer available, and a `false` value is no longer valid. Please remove this flag.")
170171
}
171172

172-
experimentalFlags.BoolVar(&config.EnableExperimentalRevisionHeartbeat, "enable-experimental-revision-heartbeat", false, "enables experimental support for postgres revision heartbeat, used to create a synthetic revision on a given interval (postgres only)")
173173
experimentalFlags.BoolVar(&config.EnableExperimentalRelationshipExpiration, "enable-experimental-relationship-expiration", false, "enables experimental support for first-class relationship expiration")
174174
experimentalFlags.BoolVar(&config.EnableExperimentalWatchableSchemaCache, "enable-experimental-watchable-schema-cache", false, "enables the experimental schema cache which makes use of the Watch API for automatic updates")
175175
// TODO: these two could reasonably be put in either the Dispatch group or the Experimental group. Is there a preference?

pkg/cmd/server/server.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ type Config struct {
121121
MaxBulkExportRelationshipsLimit uint32 `debugmap:"visible"`
122122
EnableExperimentalLookupResources bool `debugmap:"visible"`
123123
EnableExperimentalRelationshipExpiration bool `debugmap:"visible"`
124-
EnableExperimentalRevisionHeartbeat bool `debugmap:"visible"`
124+
EnableRevisionHeartbeat bool `debugmap:"visible"`
125125

126126
// Additional Services
127127
MetricsAPI util.HTTPServerConfig `debugmap:"visible"`
@@ -229,7 +229,7 @@ func (c *Config) Complete(ctx context.Context) (RunnableServer, error) {
229229
// are at most the number of elements returned from a datastore query
230230
datastorecfg.WithFilterMaximumIDCount(c.DispatchChunkSize),
231231
datastorecfg.WithEnableExperimentalRelationshipExpiration(c.EnableExperimentalRelationshipExpiration),
232-
datastorecfg.WithEnableExperimentalRevisionHeartbeat(c.EnableExperimentalRevisionHeartbeat),
232+
datastorecfg.WithEnableRevisionHeartbeat(c.EnableRevisionHeartbeat),
233233
)
234234
if err != nil {
235235
return nil, spiceerrors.NewTerminationErrorBuilder(fmt.Errorf("failed to create datastore: %w", err)).

pkg/cmd/server/zz_generated.options.go

+5-5
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)