From b64f7cf79bf6be598bb362becd774912077f5f18 Mon Sep 17 00:00:00 2001 From: Denise Li Date: Wed, 17 Jul 2024 18:52:52 -0400 Subject: [PATCH] fix: avoid insertion key dupls in `module_configuration` table by upserting on conflict (#2107) Fixes https://github.com/TBD54566975/ftl/issues/2084 This PR addresses the config side, whereas https://github.com/TBD54566975/ftl/pull/2105 fixed it for secrets. I confirmed the test fails before this change but passes with it: ``` $ go test ./common/configuration/dal/... -run TestModuleConfiguration debug:migrate: Applying: 20231103205514_init.sql debug:migrate: Applied: 20231103205514_init.sql in 134.088875ms debug:migrate: Applying: 20240704103403_create_module_secrets.sql debug:migrate: Applied: 20240704103403_create_module_secrets.sql in 5.793958ms --- FAIL: TestModuleConfiguration (0.30s) --- FAIL: TestModuleConfiguration/HandlesConflicts (0.00s) dal_test.go:108: Did not expect an error but got: duplicate key value violates unique constraint "module_configuration_module_name_key": conflict FAIL FAIL github.com/TBD54566975/ftl/common/configuration/dal 0.760s FAIL $ go test ./common/configuration/dal/... -run TestModuleConfiguration ok github.com/TBD54566975/ftl/common/configuration/dal 0.775s ``` --- common/configuration/dal/dal_test.go | 7 +++++++ common/configuration/sql/queries.sql | 3 ++- common/configuration/sql/queries.sql.go | 1 + 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/common/configuration/dal/dal_test.go b/common/configuration/dal/dal_test.go index 4016e51720..8539361a2e 100644 --- a/common/configuration/dal/dal_test.go +++ b/common/configuration/dal/dal_test.go @@ -100,6 +100,13 @@ func TestModuleConfiguration(t *testing.T) { assert.Equal(t, sortedList[i].Name, gotList[i].Name) } }) + + t.Run("HandlesConflicts", func(t *testing.T) { + err := dal.SetModuleConfiguration(ctx, optional.Some("echo"), "my_config", []byte(`""`)) + assert.NoError(t, err) + err = dal.SetModuleConfiguration(ctx, optional.Some("echo"), "my_config", []byte(`""`)) + assert.NoError(t, err) + }) } func TestModuleSecrets(t *testing.T) { diff --git a/common/configuration/sql/queries.sql b/common/configuration/sql/queries.sql index 9bcbaed4e2..9862adbd46 100644 --- a/common/configuration/sql/queries.sql +++ b/common/configuration/sql/queries.sql @@ -14,7 +14,8 @@ ORDER BY module, name; -- name: SetModuleConfiguration :exec INSERT INTO module_configuration (module, name, value) -VALUES ($1, $2, $3); +VALUES ($1, $2, $3) +ON CONFLICT (module, name) DO UPDATE SET value = $3; -- name: UnsetModuleConfiguration :exec DELETE FROM module_configuration diff --git a/common/configuration/sql/queries.sql.go b/common/configuration/sql/queries.sql.go index 5086e3f57e..99f3c30475 100644 --- a/common/configuration/sql/queries.sql.go +++ b/common/configuration/sql/queries.sql.go @@ -112,6 +112,7 @@ func (q *Queries) ListModuleSecrets(ctx context.Context) ([]ModuleSecret, error) const setModuleConfiguration = `-- name: SetModuleConfiguration :exec INSERT INTO module_configuration (module, name, value) VALUES ($1, $2, $3) +ON CONFLICT (module, name) DO UPDATE SET value = $3 ` func (q *Queries) SetModuleConfiguration(ctx context.Context, module optional.Option[string], name string, value []byte) error {