Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2284c08aa8 |
@@ -1256,8 +1256,15 @@ standard: normalized scripts in `script/` are the entrypoints for the
|
||||
development workflow. Ten of the Makefile's seventeen targets are thin
|
||||
shims that call them; `build`, `run`, `dev`, `deps`, `clean`, `css` and
|
||||
`version` are inline commands with no script behind them, though
|
||||
`build` and `version` both take their value from `script/version`. We
|
||||
provide:
|
||||
`build` and `version` both take their value from `script/version`.
|
||||
|
||||
`make check` needs the third-party browser assets in `static/`, which
|
||||
are not committed, so run `make bootstrap` (or just `make assets`) once
|
||||
after cloning. Without them the tests fail with a message naming that
|
||||
remedy. `make check` does not fetch them itself because it must not
|
||||
change any files in the repo.
|
||||
|
||||
We provide:
|
||||
|
||||
- `script/bootstrap` — install all dependencies (idempotent)
|
||||
- `script/setup` — make a fresh clone ready for development
|
||||
|
||||
@@ -438,31 +438,6 @@ func (e *Engine) processNewTask(
|
||||
return
|
||||
}
|
||||
|
||||
// Restart recovery can send and release this delivery before the
|
||||
// receiver's Notify queues it. Ownership cannot refuse a delivery
|
||||
// nobody holds, so the row decides whether it still needs sending.
|
||||
row, err := e.loadDelivery(webhookDB, task.DeliveryID)
|
||||
if err != nil {
|
||||
e.log.Error(
|
||||
"failed to load delivery",
|
||||
"delivery_id", task.DeliveryID,
|
||||
"error", err,
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if row.Status != database.DeliveryStatusPending {
|
||||
e.log.Info(
|
||||
"delivery already handled, not sent again",
|
||||
"delivery_id", task.DeliveryID,
|
||||
"event_id", task.EventID,
|
||||
"status", row.Status,
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
event := buildEventFromTask(task)
|
||||
|
||||
event, err = e.hydrateEvent(
|
||||
@@ -507,7 +482,7 @@ func (e *Engine) processRetryTask(
|
||||
return
|
||||
}
|
||||
|
||||
d, err := e.loadDelivery(
|
||||
d, err := e.loadRetryDelivery(
|
||||
webhookDB, task.DeliveryID,
|
||||
)
|
||||
if err != nil {
|
||||
@@ -1668,7 +1643,7 @@ func (e *Engine) hydrateEvent(
|
||||
return event, nil
|
||||
}
|
||||
|
||||
func (e *Engine) loadDelivery(
|
||||
func (e *Engine) loadRetryDelivery(
|
||||
webhookDB *gorm.DB, deliveryID string,
|
||||
) (*database.Delivery, error) {
|
||||
var d database.Delivery
|
||||
|
||||
@@ -273,73 +273,6 @@ func TestOwnershipIsReleasedAfterDelivery(t *testing.T) {
|
||||
)
|
||||
}
|
||||
|
||||
// TestNotifyAfterRecoveryDoesNotSendAgain is the startup race of
|
||||
// https://git.eeqj.de/sneak/webhooker/issues/299. The receiver has
|
||||
// written a delivery, restart recovery finds it pending, sends it and
|
||||
// releases it, and only then does the receiver's Notify for it arrive.
|
||||
// Nothing owns the delivery by then, so Notify takes it.
|
||||
func TestNotifyAfterRecoveryDoesNotSendAgain(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
targetID := uuid.New().String()
|
||||
s := fSweepSetup(t, targetID, "recovered")
|
||||
|
||||
event := iSeedEvent(
|
||||
t, s.WebhookDB, s.WebhookID, `{"recovered":true}`,
|
||||
)
|
||||
|
||||
d := iSeedDelivery(
|
||||
t, s.WebhookDB, event.ID, targetID,
|
||||
database.DeliveryStatusPending,
|
||||
)
|
||||
|
||||
s.Engine.ExportStart()
|
||||
|
||||
defer func() {
|
||||
require.NoError(
|
||||
t, s.Engine.ExportStop(context.Background()),
|
||||
)
|
||||
}()
|
||||
|
||||
// Restart recovery sends the delivery and lets it go.
|
||||
iWaitForDelivered(t, s.WebhookDB, d.ID)
|
||||
require.Eventually(
|
||||
t,
|
||||
func() bool {
|
||||
return s.Engine.ExportInflightHeld() == 0
|
||||
},
|
||||
5*time.Second, 20*time.Millisecond,
|
||||
)
|
||||
|
||||
body := event.Body
|
||||
|
||||
s.Engine.Notify([]delivery.Task{{
|
||||
DeliveryID: d.ID,
|
||||
EventID: event.ID,
|
||||
WebhookID: s.WebhookID,
|
||||
TargetID: targetID,
|
||||
TargetName: "recovered",
|
||||
TargetType: database.TargetTypeLog,
|
||||
Body: &body,
|
||||
EntrypointID: event.EntrypointID,
|
||||
}})
|
||||
|
||||
// Notify took the delivery, and a worker releases it once it has
|
||||
// run the task.
|
||||
require.Eventually(
|
||||
t,
|
||||
func() bool {
|
||||
return s.Engine.ExportInflightHeld() == 0
|
||||
},
|
||||
5*time.Second, 20*time.Millisecond,
|
||||
)
|
||||
|
||||
assert.Len(
|
||||
t, iResults(t, s.WebhookDB, d.ID), 1,
|
||||
"the delivery was sent a second time",
|
||||
)
|
||||
}
|
||||
|
||||
// TestRetryingRecoverySkipsASuccessfulResult is the retrying-side twin
|
||||
// of the pending reconcile. A second attempt that reached the receiver
|
||||
// and whose status write then failed sits at retrying holding a
|
||||
|
||||
Reference in New Issue
Block a user