Evita 500 senza SMTP e chiude gli incidenti overflow stale.
Reset password e mail replay usano deliver_mail; il health check overflow risolve tutte le fingerprint del kind, non solo quella sana. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -54,6 +54,8 @@ module Ops
|
||||
def process_finding(finding)
|
||||
if finding.healthy
|
||||
Ops::IncidentRecorder.resolve(fingerprint: finding.fingerprint)
|
||||
# overflow usa fingerprint diverse (at_max / orphan_idle / budget) rispetto al check sano
|
||||
Ops::IncidentRecorder.resolve_kind(finding.kind) if finding.kind == "stream_overflow"
|
||||
else
|
||||
Ops::IncidentRecorder.record(
|
||||
kind: finding.kind,
|
||||
|
||||
@@ -10,6 +10,10 @@ module Ops
|
||||
def resolve(fingerprint:)
|
||||
new.resolve(fingerprint: fingerprint)
|
||||
end
|
||||
|
||||
def resolve_kind(kind)
|
||||
new.resolve_kind(kind)
|
||||
end
|
||||
end
|
||||
|
||||
def record(finding)
|
||||
@@ -49,6 +53,10 @@ module Ops
|
||||
Ops::Incident.open.where(fingerprint: fingerprint).find_each(&:resolve!)
|
||||
end
|
||||
|
||||
def resolve_kind(kind)
|
||||
Ops::Incident.open.where(kind: kind).find_each(&:resolve!)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def fingerprint_for(finding)
|
||||
|
||||
@@ -23,7 +23,7 @@ module Recordings
|
||||
private
|
||||
|
||||
def deliver_expiring_soon(user)
|
||||
Recordings::ReplayMailer.replay_expiring_soon(recording: @recording, recipient: user).deliver_now
|
||||
MatchLiveTv.deliver_mail(Recordings::ReplayMailer.replay_expiring_soon(recording: @recording, recipient: user))
|
||||
rescue EOFError => e
|
||||
Rails.logger.warn("[Recordings::NotifyExpiring] SMTP EOF on close for #{user.email}: #{e.message}")
|
||||
end
|
||||
|
||||
@@ -19,7 +19,7 @@ module Recordings
|
||||
private
|
||||
|
||||
def deliver_replay_ready(user)
|
||||
Recordings::ReplayMailer.replay_ready(recording: @recording, recipient: user).deliver_now
|
||||
MatchLiveTv.deliver_mail(Recordings::ReplayMailer.replay_ready(recording: @recording, recipient: user))
|
||||
rescue EOFError => e
|
||||
# Aruba SMTP (465/SSL) chiude la socket prima del QUIT: la mail è già partita.
|
||||
Rails.logger.warn("[Recordings::NotifyReady] SMTP EOF on close for #{user.email}: #{e.message}")
|
||||
|
||||
@@ -13,7 +13,7 @@ module Users
|
||||
return if user.nil?
|
||||
|
||||
token = user.generate_password_reset!
|
||||
UserMailer.password_reset(user, token).deliver_now
|
||||
MatchLiveTv.deliver_mail(UserMailer.password_reset(user, token))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -109,6 +109,17 @@ RSpec.describe "Account API", type: :request do
|
||||
expect(user.reload.password_reset_digest).to be_present
|
||||
end
|
||||
|
||||
it "non va in 500 se in produzione manca SMTP" do
|
||||
allow(MatchLiveTv).to receive(:smtp_configured?).and_return(false)
|
||||
allow(Rails).to receive(:env).and_return(ActiveSupport::StringInquirer.new("production"))
|
||||
|
||||
expect {
|
||||
post "/api/v1/auth/password/forgot", params: { email: user.email }
|
||||
}.not_to change { ActionMailer::Base.deliveries.size }
|
||||
expect(response).to have_http_status(:ok)
|
||||
expect(user.reload.password_reset_digest).to be_present
|
||||
end
|
||||
|
||||
it "returns the same message for unknown emails" do
|
||||
expect {
|
||||
post "/api/v1/auth/password/forgot", params: { email: "nobody@example.com" }
|
||||
|
||||
@@ -40,6 +40,44 @@ RSpec.describe Ops::HealthChecks do
|
||||
|
||||
expect(Ops::Incident.find_by(fingerprint: "disk_space:root").status).to eq("resolved")
|
||||
end
|
||||
|
||||
it "chiude gli incidenti overflow anche se la fingerprint sana è diversa" do
|
||||
Ops::Incident.create!(
|
||||
kind: "stream_overflow",
|
||||
severity: "warning",
|
||||
status: "open",
|
||||
title: "Capacità stream al massimo",
|
||||
message: "overflow=3/3",
|
||||
metadata: {},
|
||||
fingerprint: "stream_overflow:at_max",
|
||||
occurrence_count: 1,
|
||||
first_seen_at: Time.current,
|
||||
last_seen_at: Time.current
|
||||
)
|
||||
|
||||
allow_any_instance_of(described_class).to receive(:check_stream_overflow).and_return(
|
||||
described_class::Finding.new(
|
||||
kind: "stream_overflow", severity: "info", healthy: true,
|
||||
title: "Overflow streaming OK", message: "OK", metadata: {}, fingerprint: "stream_overflow:ok"
|
||||
)
|
||||
)
|
||||
%i[
|
||||
check_disk_root check_recordings_size check_postgres check_redis check_mediamtx check_garage
|
||||
check_sidekiq_heartbeat check_sidekiq_dead check_http_rails check_rails_latency
|
||||
].each do |method|
|
||||
allow_any_instance_of(described_class).to receive(method).and_return(
|
||||
described_class::Finding.new(
|
||||
kind: "test", severity: "info", healthy: true,
|
||||
title: "OK", message: "OK", metadata: {}, fingerprint: "#{method}:ok"
|
||||
)
|
||||
)
|
||||
end
|
||||
allow_any_instance_of(described_class).to receive(:public_check_due?).and_return(false)
|
||||
|
||||
described_class.new.call
|
||||
|
||||
expect(Ops::Incident.find_by(fingerprint: "stream_overflow:at_max").status).to eq("resolved")
|
||||
end
|
||||
end
|
||||
|
||||
describe "#summary" do
|
||||
|
||||
@@ -52,4 +52,28 @@ RSpec.describe Ops::IncidentRecorder do
|
||||
expect(incident.reload.status).to eq("resolved")
|
||||
end
|
||||
end
|
||||
|
||||
describe ".resolve_kind" do
|
||||
it "chiude tutti gli incidenti aperti di quel kind" do
|
||||
at_max = described_class.record(
|
||||
kind: "stream_overflow",
|
||||
severity: "warning",
|
||||
title: "Max",
|
||||
message: "max",
|
||||
fingerprint: "stream_overflow:at_max"
|
||||
)
|
||||
orphan = described_class.record(
|
||||
kind: "stream_overflow",
|
||||
severity: "warning",
|
||||
title: "Idle",
|
||||
message: "idle",
|
||||
fingerprint: "stream_overflow:orphan_idle"
|
||||
)
|
||||
|
||||
described_class.resolve_kind("stream_overflow")
|
||||
|
||||
expect(at_max.reload.status).to eq("resolved")
|
||||
expect(orphan.reload.status).to eq("resolved")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -27,4 +27,22 @@ RSpec.describe Recordings::NotifyReady do
|
||||
|
||||
expect(recording.reload.ready_notified_at).to be_present
|
||||
end
|
||||
|
||||
it "marca notificato anche se in produzione manca SMTP" do
|
||||
recording = Recording.create!(
|
||||
stream_session: session,
|
||||
team: team,
|
||||
status: "ready",
|
||||
expires_at: 10.days.from_now,
|
||||
storage_key: "key"
|
||||
)
|
||||
allow(MatchLiveTv).to receive(:smtp_configured?).and_return(false)
|
||||
allow(Rails).to receive(:env).and_return(ActiveSupport::StringInquirer.new("production"))
|
||||
|
||||
expect {
|
||||
described_class.new(recording).call
|
||||
}.not_to change { ActionMailer::Base.deliveries.size }
|
||||
|
||||
expect(recording.reload.ready_notified_at).to be_present
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user