Skip to content

Commit

Permalink
Include code into stats last_error message
Browse files Browse the repository at this point in the history
  • Loading branch information
vankiru committed Jan 28, 2025
1 parent af9a758 commit fc7777d
Show file tree
Hide file tree
Showing 11 changed files with 163 additions and 43 deletions.
30 changes: 9 additions & 21 deletions lib/nats/io/msg.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
module NATS
class Msg
attr_accessor :subject, :reply, :data, :header
attr_reader :error

def initialize(opts = {})
@subject = opts[:subject]
Expand All @@ -26,6 +27,7 @@ def initialize(opts = {})
@sub = opts[:sub]
@ackd = false
@meta = nil
@error = nil
end

def respond(data = "")
Expand All @@ -41,31 +43,17 @@ def respond(data = "")
end

def respond_with_error(error)
message = dup
@error = NATS::Service::ErrorWrapper.new(error)

message = dup
message.subject = reply
message.reply = ""
message.data = ""

case error
when Exception
message.header = {
"Nats-Service-Error" => error.message,
"Nats-Service-Error-Code" => 500
}
when Hash
message.header = {
"Nats-Service-Error" => error[:description],
"Nats-Service-Error-Code" => error[:code]
}
message.data = @error.data

message.data = error[:data]
else
message.header = {
"Nats-Service-Error" => error.to_s,
"Nats-Service-Error-Code" => 500
}
end
message.header = {
"Nats-Service-Error" => @error.message,
"Nats-Service-Error-Code" => @error.code
}

respond_msg(message)
end
Expand Down
4 changes: 4 additions & 0 deletions lib/nats/service/endpoint.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ def initialize(name:, options:, parent:, &block)

def stop
service.client.send(:drain_sub, @handler)
rescue
# nothing we can do here
ensure
@stopped = true
end
Expand Down Expand Up @@ -54,7 +56,9 @@ def build_subject(parent, options)
def create_handler(block)
service.client.subscribe(subject, queue: queue) do |msg|
started_at = Time.now

block.call(msg)
stats.error(msg.error) if msg.error
rescue NATS::Error => error
stats.error(error)
service.stop(error)
Expand Down
29 changes: 29 additions & 0 deletions lib/nats/service/errors.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,34 @@ class InvalidVersionError < Error; end
class InvalidQueueError < Error; end

class InvalidSubjectError < Error; end

class ErrorWrapper
attr_reader :code, :message, :data

def initialize(error)
case error
when Exception
@code = 500
@message = error.message
@data = ""
when Hash
@code = error[:code]
@message = error[:description]
@data = error[:data]
when ErrorWrapper
@code = error.code
@message = error.message
@data = error.data
else
@code = 500
@message = error.to_s
@data = ""
end
end

def description
"#{code}:#{message}"
end
end
end
end
2 changes: 2 additions & 0 deletions lib/nats/service/monitoring.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ def stop
@monitors.each do |monitor|
service.client.send(:drain_sub, monitor)
end
rescue
# nothing we can do here
ensure
@monitors = nil
end
Expand Down
4 changes: 3 additions & 1 deletion lib/nats/service/stats.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,11 @@ def record(started_at)
end

def error(error)
error = ErrorWrapper.new(error)

synchronize do
@num_errors += 1
@last_error = error.message
@last_error = error.description
end
end

Expand Down
4 changes: 3 additions & 1 deletion spec/compability/service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,10 @@ def add_endpoint(parent, name, options)
end
end

attr_reader :service

def run
service = Service.new(client)
@service = Service.new(client)

client.subscribe("tests.service.core.>") do |msg|
if msg.data.empty?
Expand Down
34 changes: 24 additions & 10 deletions spec/service/endpoint_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@
request

expect(subject.stats.num_errors).to eq(1)
expect(subject.stats.last_error).to eq("Endpoint Error")
expect(subject.stats.last_error).to eq("500:Endpoint Error")
end

it "records stats" do
Expand All @@ -197,7 +197,7 @@
request

expect(subject.stats.num_errors).to eq(1)
expect(subject.stats.last_error).to eq("NATS::IO::ServerError")
expect(subject.stats.last_error).to eq("500:NATS::IO::ServerError")
end

it "records stats" do
Expand All @@ -209,18 +209,32 @@
end

describe "#stop" do
it "drains handler subscription" do
subject.stop
context "when everything goes smoothly" do
it "drains handler subscription" do
subject.stop

expect(subs.values).to include(
having_attributes(subject: "bar", drained: true)
)
expect(subs.values).to include(
having_attributes(subject: "bar", drained: true)
)
end

it "marks endpoint as stopped" do
subject.stop

expect(subject.stopped?).to be(true)
end
end

it "marks endpoint as stopped" do
subject.stop
context "when an error occurs" do
it "does not raise any errors" do
expect { subject.stop }.not_to raise_error
end

expect(subject.stopped?).to be(true)
it "marks endpoint as stopped" do
subject.stop

expect(subject.stopped?).to be(true)
end
end
end

Expand Down
53 changes: 53 additions & 0 deletions spec/service/error_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# frozen_string_literal: true

RSpec.describe NATS::Service::ErrorWrapper do
subject { described_class.new(error) }

let(:error) { {code: 503, description: "error"} }

describe "#description" do
it "combines code with message" do
expect(subject.description).to eq("503:error")
end
end

context "when error is a string" do
let(:error) { "error" }

it "builds an error from the string" do
expect(subject).to have_attributes(code: 500, message: "error", data: "")
end
end

context "when error is a hash" do
let(:error) { {code: 503, description: "error", data: "data"} }

it "builds an error from the hash" do
expect(subject).to have_attributes(code: 503, message: "error", data: "data")
end
end

context "when error is of Exception" do
let(:error) { StandardError.new("error") }

it "builds an error from the error" do
expect(subject).to have_attributes(code: 500, message: "error", data: "")
end
end

context "when error is of ErrorWrapper" do
let(:error) { described_class.new("error") }

it "builds an error from the wrapper" do
expect(subject).to have_attributes(code: 500, message: "error", data: "")
end
end

context "when error is a random object" do
let(:error) { [1, 2, 3] }

it "builds an error from the object" do
expect(subject).to have_attributes(code: 500, message: "[1, 2, 3]", data: "")
end
end
end
32 changes: 31 additions & 1 deletion spec/service/monitoring_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -114,9 +114,15 @@

describe "#stop" do
context "when monitorings has not been started yet" do
it "does nothing" do
it "does not raise any errors" do
expect { subject.stop }.not_to raise_error
end

it "marks monitoring as stopped" do
subject.stop

expect(subject.stopped?).to be(true)
end
end

context "when monitorings has been started" do
Expand All @@ -135,6 +141,30 @@
having_attributes(subject: "$SRV.STATS.foo.bar", drained: true)
)
end

it "marks monitoring as stopped" do
subject.stop

expect(subject.stopped?).to be(true)
end
end

context "when an error occurs" do
before do
allow(client).to receive(:drain_sub).and_raise("Error during drain")
end

it "does not raise any errors" do
subject.stop

expect { subject.stop }.not_to raise_error
end

it "marks monitoring as stopped" do
subject.stop

expect(subject.stopped?).to be(true)
end
end
end
end
4 changes: 2 additions & 2 deletions spec/service/stats_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@
it "sets last_error to the error message" do
subject.error(StandardError.new)

expect(subject.last_error).to eq("StandardError")
expect(subject.last_error).to eq("500:StandardError")
end
end

Expand All @@ -116,7 +116,7 @@
it "replaces last_error with the new error message" do
subject.error(StandardError.new("Error"))

expect(subject.last_error).to eq("Error")
expect(subject.last_error).to eq("500:Error")
end
end
end
Expand Down
10 changes: 3 additions & 7 deletions spec/service_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -227,17 +227,13 @@
end

it "marks service as stopped" do
begin
service.stop
rescue
nil
end
service.stop

expect(subject.stopped?).to be(true)
end

it "raises error" do
expect { service.stop }.to raise_error("Error during drain")
it "does not raise any error" do
expect { service.stop }.not_to raise_error
end
end

Expand Down

0 comments on commit fc7777d

Please sign in to comment.