fix(monitoring): MONITORING_ATTEMPTS is now exact (off-by-one); accept int or dict monitor id
- attempt is 0-based, so compare one-based: ATTEMPTS=2 really means two tries
- bridge accepts add_monitor returning {monitorID}|{id}|int (v1.2.1 returns a
dict — re-verified: first create on a fresh Kuma is HTTP 200 with the id)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
feat/portal-design
parent
5301ce4309
commit
82916167cf
|
|
@ -41,8 +41,10 @@ class RegisterMonitoring extends CustomerStep
|
||||||
throw $e; // operator wants monitoring to gate delivery
|
throw $e; // operator wants monitoring to gate delivery
|
||||||
}
|
}
|
||||||
|
|
||||||
$allowed = (int) config('provisioning.monitoring.attempts', 2);
|
// `attempt` is 0-based (this call IS attempt number attempt+1), so
|
||||||
if ($run->attempt < $allowed) {
|
// compare one-based: MONITORING_ATTEMPTS=2 really means two tries.
|
||||||
|
$allowed = max(1, (int) config('provisioning.monitoring.attempts', 2));
|
||||||
|
if ($run->attempt + 1 < $allowed) {
|
||||||
return StepResult::retry(30, 'monitoring unavailable: '.$e->getMessage());
|
return StepResult::retry(30, 'monitoring unavailable: '.$e->getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -163,11 +163,19 @@ def create_monitor(payload: MonitorIn) -> dict:
|
||||||
maxretries=payload.retries or 1, # Kuma's own field name
|
maxretries=payload.retries or 1, # Kuma's own field name
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
monitor_id = created.get("monitorID") if isinstance(created, dict) else None
|
# uptime-kuma-api 1.2.x returns {"msg": ..., "monitorID": N} (verified against
|
||||||
|
# Kuma 1.x). Accept a bare id too, so a future library change can't break us.
|
||||||
|
if isinstance(created, dict):
|
||||||
|
monitor_id = created.get("monitorID", created.get("id"))
|
||||||
|
elif isinstance(created, int):
|
||||||
|
monitor_id = created
|
||||||
|
else:
|
||||||
|
monitor_id = None
|
||||||
|
|
||||||
if monitor_id is None:
|
if monitor_id is None:
|
||||||
raise HTTPException(status_code=502, detail=f"Kuma returned no monitor id: {created}")
|
raise HTTPException(status_code=502, detail=f"Kuma returned no monitor id: {created}")
|
||||||
|
|
||||||
return {"monitor": {"id": monitor_id}}
|
return {"monitor": {"id": int(monitor_id)}}
|
||||||
|
|
||||||
|
|
||||||
@app.get("/monitors/{monitor_id}", dependencies=[Depends(require_token)])
|
@app.get("/monitors/{monitor_id}", dependencies=[Depends(require_token)])
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,7 @@ Alle Monitor-Routen erfordern `Authorization: Bearer $BRIDGE_TOKEN`.
|
||||||
Monitoring ist Beobachtung, nicht das Produkt. Fällt Kuma oder die Bridge aus,
|
Monitoring ist Beobachtung, nicht das Produkt. Fällt Kuma oder die Bridge aus,
|
||||||
darf die Bereitstellung eines **bezahlten** Kunden nicht scheitern:
|
darf die Bereitstellung eines **bezahlten** Kunden nicht scheitern:
|
||||||
|
|
||||||
- Der Schritt `register_monitoring` versucht es `MONITORING_ATTEMPTS` mal (Standard 2),
|
- Der Schritt `register_monitoring` versucht es genau `MONITORING_ATTEMPTS` mal (Standard 2 = 1 Versuch + 1 Wiederholung),
|
||||||
- danach läuft die Bereitstellung **degradiert** weiter und schreibt ein
|
- danach läuft die Bereitstellung **degradiert** weiter und schreibt ein
|
||||||
sichtbares `info`-Ereignis in die Admin-Konsole,
|
sichtbares `info`-Ereignis in die Admin-Konsole,
|
||||||
- mit `MONITORING_REQUIRED=true` wird Monitoring stattdessen erzwungen (der Lauf
|
- mit `MONITORING_REQUIRED=true` wird Monitoring stattdessen erzwungen (der Lauf
|
||||||
|
|
|
||||||
|
|
@ -371,13 +371,14 @@ it('keeps provisioning when monitoring is unreachable (retry, then degrade)', fu
|
||||||
$s['monitoring']->failWith = 'connection refused';
|
$s['monitoring']->failWith = 'connection refused';
|
||||||
['run' => $run, 'instance' => $instance] = reservedRun();
|
['run' => $run, 'instance' => $instance] = reservedRun();
|
||||||
|
|
||||||
// Early attempts retry — the outage may be transient.
|
// MONITORING_ATTEMPTS=2 means exactly two tries: attempt 0 retries…
|
||||||
|
config()->set('provisioning.monitoring.attempts', 2);
|
||||||
$first = app(RegisterMonitoring::class)->execute($run->fresh());
|
$first = app(RegisterMonitoring::class)->execute($run->fresh());
|
||||||
expect($first->type)->toBe('retry')->and($first->reason)->toContain('connection refused');
|
expect($first->type)->toBe('retry')->and($first->reason)->toContain('connection refused');
|
||||||
|
|
||||||
// Once the allowance is used up, continue DEGRADED with a visible event
|
// …and the SECOND try (attempt 1) is the last: continue DEGRADED with a
|
||||||
// instead of failing a paid customer's provisioning.
|
// visible event instead of failing a paid customer's provisioning.
|
||||||
$run->update(['attempt' => (int) config('provisioning.monitoring.attempts', 2)]);
|
$run->update(['attempt' => 1]);
|
||||||
expect(app(RegisterMonitoring::class)->execute($run->fresh())->type)->toBe('advance');
|
expect(app(RegisterMonitoring::class)->execute($run->fresh())->type)->toBe('advance');
|
||||||
|
|
||||||
expect($instance->fresh()->monitoringTargets()->count())->toBe(0)
|
expect($instance->fresh()->monitoringTargets()->count())->toBe(0)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue