feat(tfstated): allow configuration of version history limit via environment variable

This commit is contained in:
Julien Dessaux 2024-10-18 00:01:50 +02:00
parent 4c2032e1f0
commit 1ebf0341dd
Signed by: adyxax
GPG key ID: F92E51B86E07177E
5 changed files with 43 additions and 9 deletions

View file

@ -10,6 +10,7 @@ import (
"net/http"
"os"
"os/signal"
"strconv"
"sync"
"time"
@ -42,6 +43,14 @@ func run(
if err := db.SetDataEncryptionKey(dataEncryptionKey); err != nil {
return err
}
versionsHistoryLimit := getenv("VERSIONS_HISTORY_LIMIT")
if versionsHistoryLimit != "" {
n, err := strconv.Atoi(versionsHistoryLimit)
if err != nil {
return fmt.Errorf("failed to parse the VERSIONS_HISTORY_LIMIT environment variable: %w", err)
}
db.SetVersionsHistoryLimit(n)
}
mux := http.NewServeMux()
addRoutes(

View file

@ -18,6 +18,7 @@ var baseURI = url.URL{
Path: "/",
Scheme: "http",
}
var db *database.DB
func TestMain(m *testing.M) {
ctx := context.Background()
@ -27,7 +28,8 @@ func TestMain(m *testing.M) {
Port: "8081",
}
_ = os.Remove("./test.db")
db, err := database.NewDB(ctx, "./test.db")
var err error
db, err = database.NewDB(ctx, "./test.db")
if err != nil {
fmt.Fprintf(os.Stderr, "%+v\n", err)
os.Exit(1)
@ -36,6 +38,8 @@ func TestMain(m *testing.M) {
switch key {
case "DATA_ENCRYPTION_KEY":
return "hP3ZSCnY3LMgfTQjwTaGrhKwdA0yXMXIfv67OJnntqM="
case "VERSIONS_HISTORY_LIMIT":
return "3"
default:
return ""
}

View file

@ -30,6 +30,9 @@ func TestPost(t *testing.T) {
{"GET", url.URL{Path: "/test_post"}, nil, "the_test_post4", http.StatusOK, "/test_post"},
{"POST", url.URL{Path: "/test_post"}, strings.NewReader("the_test_post5"), "", http.StatusOK, "without lock ID in query string on a locked state"},
{"GET", url.URL{Path: "/test_post"}, nil, "the_test_post5", http.StatusOK, "/test_post"},
{"POST", url.URL{Path: "/test_post"}, strings.NewReader("the_test_post6"), "", http.StatusOK, "another post just to make sure the history limit works"},
{"POST", url.URL{Path: "/test_post"}, strings.NewReader("the_test_post7"), "", http.StatusOK, "another post just to make sure the history limit works"},
{"POST", url.URL{Path: "/test_post"}, strings.NewReader("the_test_post8"), "", http.StatusOK, "another post just to make sure the history limit works"},
}
for _, tt := range tests {
runHTTPRequest(tt.method, &tt.uri, tt.body, func(r *http.Response, err error) {
@ -46,4 +49,15 @@ func TestPost(t *testing.T) {
}
})
}
var n int
err := db.QueryRow(`SELECT COUNT(versions.id)
FROM versions
JOIN states ON states.id = versions.state_id
WHERE states.name = "/test_post"`).Scan(&n)
if err != nil {
t.Fatalf("failed to count versions for the /test_post state: %s", err)
}
if n != 3 {
t.Fatalf("there should only be 3 versions of the /test_post state, got %d", n)
}
}

View file

@ -29,6 +29,7 @@ type DB struct {
ctx context.Context
dataEncryptionKey scrypto.AES256Key
readDB *sql.DB
versionsHistoryLimit int
writeDB *sql.DB
}
@ -58,6 +59,7 @@ func NewDB(ctx context.Context, url string) (*DB, error) {
db := DB{
ctx: ctx,
readDB: readDB,
versionsHistoryLimit: 64,
writeDB: writeDB,
}
if _, err = db.Exec("PRAGMA foreign_keys = ON"); err != nil {
@ -101,3 +103,7 @@ func (db *DB) QueryRow(query string, args ...any) *sql.Row {
func (db *DB) SetDataEncryptionKey(s string) error {
return db.dataEncryptionKey.FromBase64(s)
}
func (db *DB) SetVersionsHistoryLimit(n int) {
db.versionsHistoryLimit = n
}

View file

@ -102,7 +102,8 @@ func (db *DB) SetState(name string, data []byte, lockID string) (bool, error) {
JOIN states ON states.id = versions.state_id
WHERE states.name = :name
ORDER BY versions.id DESC
LIMIT 64));`,
LIMIT :limit));`,
sql.Named("limit", db.versionsHistoryLimit),
sql.Named("name", name),
)
if err != nil {