bumbleworks-api 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +10 -0
- data/.rspec +3 -0
- data/.ruby-version +1 -0
- data/Gemfile +3 -0
- data/LICENSE.txt +22 -0
- data/README.md +25 -0
- data/Rakefile +9 -0
- data/bumbleworks-api.gemspec +32 -0
- data/config.ru +13 -0
- data/lib/bumbleworks/api.rb +15 -0
- data/lib/bumbleworks/api/config/application.rb +10 -0
- data/lib/bumbleworks/api/config/routes.rb +34 -0
- data/lib/bumbleworks/api/controllers/application_controller.rb +6 -0
- data/lib/bumbleworks/api/controllers/entities_controller.rb +25 -0
- data/lib/bumbleworks/api/controllers/errors_controller.rb +32 -0
- data/lib/bumbleworks/api/controllers/expressions_controller.rb +29 -0
- data/lib/bumbleworks/api/controllers/processes_controller.rb +29 -0
- data/lib/bumbleworks/api/controllers/tasks_controller.rb +43 -0
- data/lib/bumbleworks/api/controllers/trackers_controller.rb +13 -0
- data/lib/bumbleworks/api/controllers/workers_controller.rb +51 -0
- data/lib/bumbleworks/api/lib/presenter.rb +32 -0
- data/lib/bumbleworks/api/lib/presenters/entity_class_presenter.rb +19 -0
- data/lib/bumbleworks/api/lib/presenters/entity_presenter.rb +13 -0
- data/lib/bumbleworks/api/lib/presenters/error_presenter.rb +15 -0
- data/lib/bumbleworks/api/lib/presenters/expression_presenter.rb +17 -0
- data/lib/bumbleworks/api/lib/presenters/process_presenter.rb +32 -0
- data/lib/bumbleworks/api/lib/presenters/task_presenter.rb +15 -0
- data/lib/bumbleworks/api/lib/presenters/tracker_presenter.rb +16 -0
- data/lib/bumbleworks/api/lib/presenters/worker_presenter.rb +30 -0
- data/lib/bumbleworks/api/lib/time_support.rb +23 -0
- data/lib/bumbleworks/api/version.rb +5 -0
- data/playground_setup.rb +30 -0
- data/spec/controllers/entities_controller_spec.rb +32 -0
- data/spec/controllers/errors_controller_spec.rb +42 -0
- data/spec/controllers/expressions_controller_spec.rb +40 -0
- data/spec/controllers/processes_controller_spec.rb +50 -0
- data/spec/controllers/tasks_controller_spec.rb +82 -0
- data/spec/controllers/trackers_controller_spec.rb +25 -0
- data/spec/controllers/workers_controller_spec.rb +113 -0
- data/spec/fixtures/bumbleworks_config.rb +10 -0
- data/spec/fixtures/entities/mock_entity.rb +38 -0
- data/spec/fixtures/entities/widget.rb +9 -0
- data/spec/fixtures/entities/widgety_fidget.rb +5 -0
- data/spec/fixtures/participants.rb +3 -0
- data/spec/fixtures/participants/naughty_participant.rb +16 -0
- data/spec/fixtures/processes/error_process.rb +3 -0
- data/spec/fixtures/processes/task_process.rb +9 -0
- data/spec/fixtures/processes/waiting_process.rb +8 -0
- data/spec/lib/presenter_spec.rb +29 -0
- data/spec/lib/presenters/entity_class_presenter_spec.rb +17 -0
- data/spec/lib/presenters/entity_presenter_spec.rb +15 -0
- data/spec/lib/presenters/error_presenter_spec.rb +18 -0
- data/spec/lib/presenters/expression_presenter_spec.rb +33 -0
- data/spec/lib/presenters/process_presenter_spec.rb +42 -0
- data/spec/lib/presenters/task_presenter_spec.rb +18 -0
- data/spec/lib/presenters/tracker_presenter_spec.rb +18 -0
- data/spec/lib/presenters/worker_presenter_spec.rb +30 -0
- data/spec/lib/time_support_spec.rb +42 -0
- data/spec/spec_helper.rb +39 -0
- data/spec/support/api_helper.rb +23 -0
- data/spec/support/process_helpers.rb +11 -0
- metadata +261 -0
@@ -0,0 +1,25 @@
|
|
1
|
+
describe Bumbleworks::Api::TrackersController do
|
2
|
+
before(:each) do
|
3
|
+
Bumbleworks.launch!('waiting_process')
|
4
|
+
wait_until { Bumbleworks::Tracker.count == 5 }
|
5
|
+
end
|
6
|
+
|
7
|
+
describe "#index" do
|
8
|
+
it "returns all existing trackers" do
|
9
|
+
get "/trackers"
|
10
|
+
expect(last_response.body).to eq(
|
11
|
+
json_presentation_of(Bumbleworks::Tracker.all, :as => 'Tracker')
|
12
|
+
)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "#show" do
|
17
|
+
it "returns requested instance" do
|
18
|
+
tracker = Bumbleworks::Tracker.all.first
|
19
|
+
get "/trackers/#{tracker.id}"
|
20
|
+
expect(last_response.body).to eq(
|
21
|
+
json_presentation_of(tracker, :as => 'Tracker')
|
22
|
+
)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
describe Bumbleworks::Api::WorkersController do
|
2
|
+
before(:each) do
|
3
|
+
Bumbleworks.start_worker!
|
4
|
+
allow(Time).to receive(:now).and_return(Time.now)
|
5
|
+
end
|
6
|
+
|
7
|
+
describe "#index" do
|
8
|
+
it "returns all workers" do
|
9
|
+
allow(Time).to receive(:now).and_return(Time.now)
|
10
|
+
workers = Bumbleworks::Worker::Info.all
|
11
|
+
expect(Bumbleworks::Worker).to receive(:refresh_worker_info)
|
12
|
+
get "/workers"
|
13
|
+
expect(last_response.body).to eq(
|
14
|
+
json_presentation_of(workers, :as => 'Worker')
|
15
|
+
)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "#show" do
|
20
|
+
it "returns requested worker" do
|
21
|
+
worker = Bumbleworks::Worker::Info.first
|
22
|
+
expect(Bumbleworks::Worker).to receive(:refresh_worker_info)
|
23
|
+
get "/workers/#{worker.id}"
|
24
|
+
expect(last_response.body).to eq(
|
25
|
+
json_presentation_of(worker, :as => 'Worker')
|
26
|
+
)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "#change_state" do
|
31
|
+
let(:worker) { Bumbleworks::Worker::Info.first }
|
32
|
+
before(:each) do
|
33
|
+
allow(Bumbleworks::Worker::Info).to receive(:[]).
|
34
|
+
with(worker.id).and_return(worker)
|
35
|
+
end
|
36
|
+
|
37
|
+
it "sends shutdown to given worker" do
|
38
|
+
expect(worker).to receive(:shutdown)
|
39
|
+
put "/workers/#{worker.id}/command/shutdown"
|
40
|
+
expect(last_response.body).to eq(
|
41
|
+
{ "status" => "shutdown sent" }.to_json
|
42
|
+
)
|
43
|
+
end
|
44
|
+
|
45
|
+
it "sends pause to given worker" do
|
46
|
+
expect(worker).to receive(:pause)
|
47
|
+
put "/workers/#{worker.id}/command/pause"
|
48
|
+
expect(last_response.body).to eq(
|
49
|
+
{ "status" => "pause sent" }.to_json
|
50
|
+
)
|
51
|
+
end
|
52
|
+
|
53
|
+
it "sends unpause to given worker" do
|
54
|
+
expect(worker).to receive(:unpause)
|
55
|
+
put "/workers/#{worker.id}/command/unpause"
|
56
|
+
expect(last_response.body).to eq(
|
57
|
+
{ "status" => "unpause sent" }.to_json
|
58
|
+
)
|
59
|
+
end
|
60
|
+
|
61
|
+
it "returns 404 if unknown command is sent" do
|
62
|
+
put "/workers/#{worker.id}/command/dance"
|
63
|
+
expect(last_response.body).to eq(
|
64
|
+
{ :error => "not_found" }.to_json
|
65
|
+
)
|
66
|
+
expect(last_response.status).to eq(404)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
describe "#change_global_state" do
|
71
|
+
it "sends shutdown to all workers" do
|
72
|
+
expect(Bumbleworks::Worker).to receive(:shutdown_all)
|
73
|
+
put "/workers/command/shutdown"
|
74
|
+
expect(last_response.body).to eq(
|
75
|
+
{ "status" => "shutdown sent" }.to_json
|
76
|
+
)
|
77
|
+
end
|
78
|
+
|
79
|
+
it "sends pause to all workers" do
|
80
|
+
expect(Bumbleworks::Worker).to receive(:pause_all)
|
81
|
+
put "/workers/command/pause"
|
82
|
+
expect(last_response.body).to eq(
|
83
|
+
{ "status" => "pause sent" }.to_json
|
84
|
+
)
|
85
|
+
end
|
86
|
+
|
87
|
+
it "sends unpause to all workers" do
|
88
|
+
expect(Bumbleworks::Worker).to receive(:unpause_all)
|
89
|
+
put "/workers/command/unpause"
|
90
|
+
expect(last_response.body).to eq(
|
91
|
+
{ "status" => "unpause sent" }.to_json
|
92
|
+
)
|
93
|
+
end
|
94
|
+
|
95
|
+
it "returns 404 if unknown command is sent" do
|
96
|
+
put "/workers/command/dance"
|
97
|
+
expect(last_response.body).to eq(
|
98
|
+
{ :error => "not_found" }.to_json
|
99
|
+
)
|
100
|
+
expect(last_response.status).to eq(404)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
describe "#prune_stopped_workers" do
|
105
|
+
it "prunes stale worker info" do
|
106
|
+
expect(Bumbleworks::Worker::Info).to receive(:purge_stale_worker_info)
|
107
|
+
delete "/workers/prune"
|
108
|
+
expect(last_response.body).to eq(
|
109
|
+
{ :status => "pruned_stale_worker_info" }.to_json
|
110
|
+
)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
class MockEntity
|
2
|
+
class << self
|
3
|
+
def collection
|
4
|
+
@collection ||= {}
|
5
|
+
end
|
6
|
+
|
7
|
+
def all
|
8
|
+
collection.values
|
9
|
+
end
|
10
|
+
|
11
|
+
def truncate!
|
12
|
+
@collection = {}
|
13
|
+
end
|
14
|
+
|
15
|
+
def first_by_identifier(identifier)
|
16
|
+
collection[identifier.to_i]
|
17
|
+
end
|
18
|
+
|
19
|
+
def count
|
20
|
+
all.count
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def initialize(identifier)
|
25
|
+
@identifier = identifier
|
26
|
+
self.class.collection[identifier] = self
|
27
|
+
end
|
28
|
+
|
29
|
+
def id
|
30
|
+
@identifier
|
31
|
+
end
|
32
|
+
|
33
|
+
def update(hsh)
|
34
|
+
hsh.each do |key, value|
|
35
|
+
self.send(:"#{key}=", value)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class NaughtyParticipant
|
2
|
+
class StupidError < StandardError; end
|
3
|
+
include Bumbleworks::LocalParticipant
|
4
|
+
|
5
|
+
class << self
|
6
|
+
attr_accessor :naughty_is_ok
|
7
|
+
end
|
8
|
+
|
9
|
+
def on_workitem
|
10
|
+
if self.class.naughty_is_ok
|
11
|
+
reply
|
12
|
+
else
|
13
|
+
raise StupidError, 'Oh crumb.'
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
describe Bumbleworks::Api::Presenter do
|
2
|
+
describe ".from_array" do
|
3
|
+
it "maps each object to its presentation, passing in_collection arg" do
|
4
|
+
allow(described_class).to receive(:new).
|
5
|
+
with(:a, :in_collection => true).
|
6
|
+
and_return(:a_p)
|
7
|
+
allow(described_class).to receive(:new).
|
8
|
+
with(:b, :in_collection => true).
|
9
|
+
and_return(:b_p)
|
10
|
+
expect(described_class.from_array([:a, :b])).to eq(
|
11
|
+
[:a_p, :b_p]
|
12
|
+
)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe ".present" do
|
17
|
+
it "instantiates single presenter if not given array" do
|
18
|
+
allow(described_class).to receive(:new).with(:a).and_return(:a_p)
|
19
|
+
expect(described_class.present(:a)).to eq(:a_p)
|
20
|
+
end
|
21
|
+
|
22
|
+
it "returns result of .from_array if given array" do
|
23
|
+
allow(described_class).to receive(:from_array).
|
24
|
+
with([:a, :b]).
|
25
|
+
and_return(:presented_array)
|
26
|
+
expect(described_class.present([:a, :b])).to eq(:presented_array)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
describe Bumbleworks::Api::EntityClassPresenter do
|
2
|
+
let(:presented) { Widget }
|
3
|
+
subject { described_class.new(presented) }
|
4
|
+
|
5
|
+
describe "#to_hash" do
|
6
|
+
it "returns hash representation of entity class" do
|
7
|
+
allow(presented).to receive(:count).and_return(10)
|
8
|
+
expect(subject.to_hash).to eq({
|
9
|
+
:class => 'Widget',
|
10
|
+
:count => 10,
|
11
|
+
:registered_processes => [
|
12
|
+
{ :name => :task_process, :attribute => :task_process_identifier }
|
13
|
+
]
|
14
|
+
})
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
describe Bumbleworks::Api::EntityPresenter do
|
2
|
+
let(:presented) { Widget.new(42) }
|
3
|
+
subject { described_class.new(presented) }
|
4
|
+
|
5
|
+
describe "#to_hash" do
|
6
|
+
it "returns hash representation of entity class" do
|
7
|
+
allow(presented).to receive(:processes).and_return([:a, :b])
|
8
|
+
expect(subject.to_hash).to eq({
|
9
|
+
:identifier => 42,
|
10
|
+
:name => "Widget 42",
|
11
|
+
:process_count => 2
|
12
|
+
})
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
describe Bumbleworks::Api::ErrorPresenter do
|
2
|
+
let(:presented) { Bumbleworks.errors.first }
|
3
|
+
subject { described_class.new(presented) }
|
4
|
+
|
5
|
+
describe "#to_hash" do
|
6
|
+
it "returns hash representation of error" do
|
7
|
+
process = Bumbleworks.launch!('error_process')
|
8
|
+
wait_until { Bumbleworks.errors.count == 1 }
|
9
|
+
expect(subject.to_hash).to eq({
|
10
|
+
:process_id => process.id,
|
11
|
+
:expression_id => presented.expression.expid,
|
12
|
+
:error_class_name => "NaughtyParticipant::StupidError",
|
13
|
+
:message => "Oh crumb.",
|
14
|
+
:backtrace => presented.backtrace
|
15
|
+
})
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
describe Bumbleworks::Api::ExpressionPresenter do
|
2
|
+
let(:process) { Bumbleworks.launch!('task_process') }
|
3
|
+
let(:presented) { process.expression_at_position('0_0_1') }
|
4
|
+
|
5
|
+
subject { described_class.new(presented) }
|
6
|
+
|
7
|
+
describe "#to_hash" do
|
8
|
+
it "returns hash representation of expression" do
|
9
|
+
wait_until { process.tasks.count == 2 }
|
10
|
+
expect(subject.to_hash).to eq({
|
11
|
+
:expression_id => presented.expid,
|
12
|
+
:process_id => presented.process.id,
|
13
|
+
:tree => presented.tree
|
14
|
+
})
|
15
|
+
end
|
16
|
+
|
17
|
+
context "with error" do
|
18
|
+
let(:process) { Bumbleworks.launch!('error_process') }
|
19
|
+
let(:presented) { process.expression_at_position('0_0') }
|
20
|
+
|
21
|
+
it "includes presented error" do
|
22
|
+
wait_until { process.reload.errors.count == 1 }
|
23
|
+
error = Bumbleworks.errors.first
|
24
|
+
expect(subject.to_hash).to eq({
|
25
|
+
:expression_id => presented.expid,
|
26
|
+
:process_id => presented.process.id,
|
27
|
+
:tree => presented.tree,
|
28
|
+
:error => Bumbleworks::Api::ErrorPresenter.present(error).to_hash
|
29
|
+
})
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
describe Bumbleworks::Api::ProcessPresenter do
|
2
|
+
let(:presented) { Bumbleworks.launch!('task_process', :entity => widget) }
|
3
|
+
let(:widget) { Widget.new(41) }
|
4
|
+
|
5
|
+
describe "#to_hash" do
|
6
|
+
context "not in collection" do
|
7
|
+
subject { described_class.new(presented) }
|
8
|
+
|
9
|
+
it "returns full hash representation of process" do
|
10
|
+
wait_until { presented.tasks.count == 2 }
|
11
|
+
expect(subject.to_hash).to eq({
|
12
|
+
:id => presented.id,
|
13
|
+
:definition_name => "task_process",
|
14
|
+
:subscribed_events => [],
|
15
|
+
:entity => Bumbleworks::Api::EntityPresenter.present(widget).to_hash,
|
16
|
+
:entity_name => widget.to_s,
|
17
|
+
:original_tree => presented.original_tree
|
18
|
+
})
|
19
|
+
end
|
20
|
+
|
21
|
+
it "doesn't include entity if process has none" do
|
22
|
+
wait_until { presented.tasks.count == 2 }
|
23
|
+
allow(presented).to receive(:entity).and_return(nil)
|
24
|
+
expect(subject.to_hash.keys).not_to include(:entity)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
context "in collection" do
|
29
|
+
subject { described_class.new(presented, :in_collection => true) }
|
30
|
+
|
31
|
+
it "returns minimal hash representation of process" do
|
32
|
+
wait_until { presented.tasks.count == 2 }
|
33
|
+
expect(subject.to_hash).to eq({
|
34
|
+
:id => presented.id,
|
35
|
+
:definition_name => "task_process",
|
36
|
+
:entity_name => widget.to_s,
|
37
|
+
:subscribed_events => []
|
38
|
+
})
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
describe Bumbleworks::Api::TaskPresenter do
|
2
|
+
let(:process) { Bumbleworks.launch!('task_process') }
|
3
|
+
let(:presented) { process.tasks.next_available }
|
4
|
+
subject { described_class.new(presented) }
|
5
|
+
|
6
|
+
describe "#to_hash" do
|
7
|
+
it "returns hash representation of entity class" do
|
8
|
+
presented.claim('oscar')
|
9
|
+
expect(subject.to_hash).to eq({
|
10
|
+
:id => presented.id,
|
11
|
+
:name => presented.to_s,
|
12
|
+
:claimant => 'oscar',
|
13
|
+
:process_id => presented.wfid,
|
14
|
+
:role => presented.role
|
15
|
+
})
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
describe Bumbleworks::Api::TrackerPresenter do
|
2
|
+
let(:process) { Bumbleworks.launch!('waiting_process') }
|
3
|
+
let(:presented) { Bumbleworks::Tracker.all.first }
|
4
|
+
subject { described_class.new(presented) }
|
5
|
+
|
6
|
+
describe "#to_hash" do
|
7
|
+
it "returns hash representation of entity class" do
|
8
|
+
expect(subject.to_hash).to eq({
|
9
|
+
:id => presented.id,
|
10
|
+
:waiting_expression => presented.waiting_expression,
|
11
|
+
:original_hash => presented.original_hash,
|
12
|
+
:action => presented.action,
|
13
|
+
:conditions => presented.conditions,
|
14
|
+
:process_id => presented.wfid
|
15
|
+
})
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|