Skip to content

Commit

Permalink
feat: add crdb consistency guarantees
Browse files Browse the repository at this point in the history
  • Loading branch information
aeneasr committed Oct 6, 2023
1 parent 45f6c90 commit f933407
Show file tree
Hide file tree
Showing 2 changed files with 114 additions and 0 deletions.
88 changes: 88 additions & 0 deletions crdbx/staleness.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package crdbx

import (
"github.com/gobuffalo/pop/v6"
"github.com/ory/x/sqlcon"
"net/http"
)

// swagger:model consistencyRequestParameters
type ConsistencyRequestParameters struct {
// Read Consistency Level
//
// The read consistency level determines the consistency guarantee for reads and queries:
//
// - strong (slow): The read is guaranteed to return the most recent data committed at the start of the read.
// - eventual (very fast): The result will return data that is about 4.8 seconds old.
//
// Ory Network projects created before October 2023 default to strong consistency and projects created after
// October 2023 default to eventual consistency, if this parameter is not set.
//
// The default consistency guarantee can be changed in the Ory Network Console or using the Ory CLI with
// `ory patch project --replace '/database/default_consistency_level="strong"'`.
//
// This feature is fully functional only in Ory Network.
//
// required: false
// in: query
// example: eventual
Consistency string `json:"per_page"`
}

// ConsistencyLevel is the consistency level.
type ConsistencyLevel string

var (
// ConsistencyLevelUnset is the unset / default consistency level.
ConsistencyLevelUnset ConsistencyLevel = ""
// ConsistencyLevelStrong is the strong consistency level.
ConsistencyLevelStrong ConsistencyLevel = "strong"
// ConsistencyLevelEventual is the eventual consistency level using follower read timestamps.
ConsistencyLevelEventual ConsistencyLevel = "eventual"
)

// ConsistencyLevelFromRequest extracts the consistency level from a request.
func ConsistencyLevelFromRequest(r *http.Request) ConsistencyLevel {
return ConsistencyLevelFromString(r.URL.Query().Get("consistency"))
}

// ConsistencyLevelFromString converts a string to a ConsistencyLevel.
// If the string is not recognized or unset, ConsistencyLevelStrong is returned.
func ConsistencyLevelFromString(in string) ConsistencyLevel {
switch in {
case string(ConsistencyLevelStrong):
return ConsistencyLevelStrong
case string(ConsistencyLevelEventual):
return ConsistencyLevelEventual
case string(ConsistencyLevelUnset):
return ConsistencyLevelStrong
}
return ConsistencyLevelStrong
}

// SetTransactionConsistency sets the transaction consistency level for CockroachDB.
func SetTransactionConsistency(c *pop.Connection, level ConsistencyLevel, fallback ConsistencyLevel) error {
if c.Dialect.Name() != "cockroach" {
// Only CockroachDB supports this.
return nil
}

switch level {
case ConsistencyLevelStrong:
// Nothing to do
return nil
case ConsistencyLevelEventual:
// Jumps to end of function
case ConsistencyLevelUnset:
fallthrough
default:
if fallback != ConsistencyLevelEventual {
// Nothing to do
return nil
}

// Jumps to end of function
}

return sqlcon.HandleError(c.RawQuery("SET TRANSACTION AS OF SYSTEM TIME follower_read_timestamp()").Exec())
}
26 changes: 26 additions & 0 deletions crdbx/staleness_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package crdbx

import (
"github.com/ory/x/urlx"
"github.com/stretchr/testify/assert"
"net/http"
"testing"
)

func TestConsistencyLevelFromString(t *testing.T) {
assert.Equal(t, ConsistencyLevelStrong, ConsistencyLevelFromString(""))
assert.Equal(t, ConsistencyLevelStrong, ConsistencyLevelFromString("strong"))
assert.Equal(t, ConsistencyLevelEventual, ConsistencyLevelFromString("eventual"))
assert.Equal(t, ConsistencyLevelStrong, ConsistencyLevelFromString("lol"))
}

func TestConsistencyLevelFromRequest(t *testing.T) {
assert.Equal(t, ConsistencyLevelStrong, ConsistencyLevelFromRequest(&http.Request{URL: urlx.ParseOrPanic("/?consistency=strong")}))
assert.Equal(t, ConsistencyLevelEventual, ConsistencyLevelFromRequest(&http.Request{URL: urlx.ParseOrPanic("/?consistency=eventual")}))
assert.Equal(t, ConsistencyLevelStrong, ConsistencyLevelFromRequest(&http.Request{URL: urlx.ParseOrPanic("/?consistency=asdf")}))

}

func TestSetTransactionConsistency(t *testing.T) {
t.Fatalf("todo")
}

0 comments on commit f933407

Please sign in to comment.