diff --git a/lib/gush/cli.rb b/lib/gush/cli.rb index 7244ca5..c54b804 100644 --- a/lib/gush/cli.rb +++ b/lib/gush/cli.rb @@ -74,9 +74,7 @@ def rm(workflow_id) option :start, type: :numeric, default: nil option :stop, type: :numeric, default: nil def list(start=nil, stop=nil) - workflows = client.workflow_ids(start, stop).map do |id| - client.find_workflow(id) - end + workflows = client.workflows(start, stop) rows = workflows.map do |workflow| [workflow.id, (Time.at(workflow.started_at) if workflow.started_at), workflow.class, {alignment: :center, value: status_for(workflow)}] diff --git a/lib/gush/client.rb b/lib/gush/client.rb index 144f25d..27011e5 100644 --- a/lib/gush/client.rb +++ b/lib/gush/client.rb @@ -104,7 +104,11 @@ def workflow_ids(start=nil, stop=nil, by_ts: false, order: :asc) end def workflows(start=nil, stop=nil, **kwargs) - workflow_ids(start, stop, **kwargs).map { |id| find_workflow(id) } + workflow_ids(start, stop, **kwargs).map do |id| + find_workflow(id) + rescue WorkflowClassDoesNotExist, JobClassDoesNotExist + nil + end.compact end def workflows_count @@ -285,6 +289,8 @@ def workflow_from_hash(hash, nodes = []) globals: hash[:globals], internal_state: internal_state ) + rescue NameError + raise WorkflowClassDoesNotExist.new("Workflow #{hash[:klass]} doesn't exist") end def redis diff --git a/lib/gush/errors.rb b/lib/gush/errors.rb index 6c65936..db7f5da 100644 --- a/lib/gush/errors.rb +++ b/lib/gush/errors.rb @@ -1,4 +1,6 @@ module Gush class WorkflowNotFound < StandardError; end + class WorkflowClassDoesNotExist < StandardError; end + class JobClassDoesNotExist < StandardError; end class DependencyLevelTooDeep < StandardError; end end diff --git a/lib/gush/job.rb b/lib/gush/job.rb index 9c0c962..ae1d3da 100644 --- a/lib/gush/job.rb +++ b/lib/gush/job.rb @@ -38,6 +38,8 @@ def to_json(options = {}) def self.from_hash(hash) hash[:klass].constantize.new(hash) + rescue NameError + raise JobClassDoesNotExist.new("Job #{hash[:klass]} doesn't exist") end def output(data) diff --git a/spec/gush/job_spec.rb b/spec/gush/job_spec.rb index eb3a971..29d8d09 100644 --- a/spec/gush/job_spec.rb +++ b/spec/gush/job_spec.rb @@ -165,5 +165,11 @@ expect(job.started_at).to eq(55) expect(job.enqueued_at).to eq(444) end + + it "raises JobClassDoesNotExist if the job class is no longer defined" do + expect { + described_class.from_hash({klass: 'NonExistentJob'}) + }.to raise_error(Gush::JobClassDoesNotExist) + end end end diff --git a/spec/gush/workflow_spec.rb b/spec/gush/workflow_spec.rb index d3a385d..efae2ef 100644 --- a/spec/gush/workflow_spec.rb +++ b/spec/gush/workflow_spec.rb @@ -78,6 +78,40 @@ def configure(*args) flow = TestWorkflow.create expect(Gush::Workflow.page.map(&:id)).to eq([flow.id]) end + + it "does not error if a stored workflow class is no longer defined in the codebase" do + flow = TestWorkflow.create + called = false + allow_any_instance_of(TestWorkflow).to receive(:to_hash).and_wrap_original do |original, *args| + called = true + original.call(*args).merge({name: 'OldDeletedWorkflow', klass: 'OldDeletedWorkflow'}) + end + expect { + flow.save + Gush::Workflow.page + }.not_to raise_error + expect { + Gush::Client.new.find_workflow(flow.id) + }.to raise_error(Gush::WorkflowClassDoesNotExist) + expect(called).to be(true) + end + + it "does not error if a workflow's job class is no longer defined" do + flow = TestWorkflow.create + called = false + allow_any_instance_of(Gush::Job).to receive(:as_json).and_wrap_original do |original, *args| + called = true + original.call(*args).merge({ klass: 'OldDeletedJob'}) + end + flow.save + expect { + Gush::Workflow.page + }.not_to raise_error + expect { + Gush::Client.new.find_workflow(flow.id) + }.to raise_error(Gush::JobClassDoesNotExist) + expect(called).to be(true) + end end describe "#save" do