Store a target's number of delivery attempts, at least one (closes #540)
check / check (push) Canceled after 0s

Target.MaxRetries (max_retries) becomes Target.MaxAttempts
(max_attempts), and the form field, parser and ceiling are renamed to
match. The column is NOT NULL and a check constraint refuses a value
below 1, so every target, whatever its type, is stored with at least
1. 1 is a single attempt with no circuit breaker; above 1 retries
behind the breaker up to that many attempts. Both target forms refuse
0 and less; a blank field on the add target form gives 1, and on the
edit form keeps the stored value. The target page shows the plain
number, and the README's two paragraphs on 0 against 1 become one
sentence.

Model: opus-5-5
This commit is contained in:
2026-10-15 16:55:55 +00:00
parent c7c4ea3340
commit a69edcdb76
51 changed files with 1027 additions and 820 deletions
+7 -7
View File
@@ -363,11 +363,11 @@ func checkAddEachTargetType(ctx context.Context, t *testing.T, url string) {
}{
{
"http", "http",
"csrf_token name type url headers timeout max_retries",
"csrf_token name type url headers timeout max_attempts",
map[string]string{"url": publicTargetURL},
},
{
"slack", "slack", "csrf_token name type url max_retries",
"slack", "slack", "csrf_token name type url max_attempts",
map[string]string{"url": publicTargetURL},
},
{
@@ -639,11 +639,11 @@ func checkRefusedEdits(
values map[string]string
}{
{page + "/targets/" + targetID + "/edit", map[string]string{
"#name": "edited-target",
"#url": "http://127.0.0.1/hook",
"#headers": "X-Edited: kept",
"#timeout": "12",
"#max_retries": "3",
"#name": "edited-target",
"#url": "http://127.0.0.1/hook",
"#headers": "X-Edited: kept",
"#timeout": "12",
"#max_attempts": "3",
}},
{page + "/edit", map[string]string{
"#name": "edited-webhook",
+5 -4
View File
@@ -27,10 +27,11 @@ func TestHook_DownloadArchive(t *testing.T) {
env.seedTarget(t, wh.ID)
archive := &database.Target{
WebhookID: wh.ID,
Name: "kept",
Type: database.TargetTypeDatabase,
Active: true,
WebhookID: wh.ID,
Name: "kept",
Type: database.TargetTypeDatabase,
Active: true,
MaxAttempts: 1,
}
require.NoError(t,
env.db.DB().Omit(clause.Associations).Create(archive).Error,
+6 -5
View File
@@ -402,11 +402,12 @@ func (e *testEnv) seedTarget(
t.Helper()
tgt := &database.Target{
WebhookID: webhookID,
Name: "routed-target",
Type: database.TargetTypeHTTP,
Active: true,
Config: `{"url":"http://93.184.216.34/hook"}`,
WebhookID: webhookID,
Name: "routed-target",
Type: database.TargetTypeHTTP,
Active: true,
Config: `{"url":"http://93.184.216.34/hook"}`,
MaxAttempts: 1,
}
require.NoError(