startback-jobs 0.14.0 → 0.14.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (119) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +3 -2
  3. data/lib/startback/ext/support/operation_runner.rb +17 -0
  4. data/lib/startback/ext/web/api.rb +12 -0
  5. data/lib/startback/ext.rb +2 -2
  6. data/lib/startback/jobs/agent.rb +15 -0
  7. data/lib/startback/jobs/api.rb +12 -0
  8. data/lib/startback/jobs/event/job_created.rb +8 -0
  9. data/lib/startback/jobs/event/job_ran.rb +8 -0
  10. data/lib/startback/jobs/event.rb +8 -0
  11. data/lib/startback/jobs/model/job.rb +35 -0
  12. data/lib/startback/jobs/model.rb +12 -0
  13. data/lib/startback/jobs/operation/create_job.rb +37 -0
  14. data/lib/startback/jobs/operation/run_job.rb +35 -0
  15. data/lib/startback/jobs/operation.rb +8 -0
  16. data/lib/startback/jobs/services.rb +25 -0
  17. data/lib/startback/jobs/support/job_result/embedded.rb +15 -0
  18. data/lib/startback/jobs/support/job_result/not_ready.rb +15 -0
  19. data/lib/startback/jobs/support/job_result/redirect.rb +32 -0
  20. data/lib/startback/jobs/support/job_result.rb +31 -0
  21. data/lib/startback/jobs/support.rb +1 -0
  22. data/lib/startback/jobs.fio +44 -0
  23. data/lib/startback/jobs.rb +23 -0
  24. data/spec/spec_helper.rb +26 -33
  25. data/spec/unit/api/test_job_result.rb +121 -0
  26. data/spec/unit/model/test_job.rb +23 -0
  27. data/spec/unit/operation/test_create_job.rb +42 -0
  28. data/spec/unit/operation/test_run_job.rb +37 -0
  29. data/spec/unit/test_finitio_schema.rb +20 -0
  30. data/tasks/test.rake +0 -1
  31. metadata +29 -92
  32. data/README.md +0 -13
  33. data/lib/startback/audit/prometheus.rb +0 -87
  34. data/lib/startback/audit/shared.rb +0 -17
  35. data/lib/startback/audit/trailer.rb +0 -129
  36. data/lib/startback/audit.rb +0 -3
  37. data/lib/startback/caching/entity_cache.rb +0 -157
  38. data/lib/startback/caching/no_store.rb +0 -28
  39. data/lib/startback/caching/store.rb +0 -34
  40. data/lib/startback/context/h_factory.rb +0 -43
  41. data/lib/startback/context/middleware.rb +0 -53
  42. data/lib/startback/context.rb +0 -122
  43. data/lib/startback/errors.rb +0 -197
  44. data/lib/startback/event/agent.rb +0 -84
  45. data/lib/startback/event/bus/bunny/async.rb +0 -162
  46. data/lib/startback/event/bus/bunny.rb +0 -1
  47. data/lib/startback/event/bus/memory/async.rb +0 -45
  48. data/lib/startback/event/bus/memory/sync.rb +0 -35
  49. data/lib/startback/event/bus/memory.rb +0 -2
  50. data/lib/startback/event/bus.rb +0 -100
  51. data/lib/startback/event/engine.rb +0 -94
  52. data/lib/startback/event/ext/context.rb +0 -5
  53. data/lib/startback/event/ext/operation.rb +0 -13
  54. data/lib/startback/event.rb +0 -47
  55. data/lib/startback/ext/date_time.rb +0 -9
  56. data/lib/startback/ext/time.rb +0 -9
  57. data/lib/startback/model.rb +0 -6
  58. data/lib/startback/operation/error_operation.rb +0 -19
  59. data/lib/startback/operation/multi_operation.rb +0 -28
  60. data/lib/startback/operation.rb +0 -78
  61. data/lib/startback/services.rb +0 -11
  62. data/lib/startback/support/data_object.rb +0 -71
  63. data/lib/startback/support/env.rb +0 -41
  64. data/lib/startback/support/fake_logger.rb +0 -18
  65. data/lib/startback/support/hooks.rb +0 -48
  66. data/lib/startback/support/log_formatter.rb +0 -34
  67. data/lib/startback/support/logger.rb +0 -34
  68. data/lib/startback/support/operation_runner.rb +0 -150
  69. data/lib/startback/support/robustness.rb +0 -157
  70. data/lib/startback/support/transaction_manager.rb +0 -25
  71. data/lib/startback/support/transaction_policy.rb +0 -33
  72. data/lib/startback/support/world.rb +0 -54
  73. data/lib/startback/support.rb +0 -26
  74. data/lib/startback/version.rb +0 -8
  75. data/lib/startback/web/api.rb +0 -99
  76. data/lib/startback/web/auto_caching.rb +0 -85
  77. data/lib/startback/web/catch_all.rb +0 -52
  78. data/lib/startback/web/cors_headers.rb +0 -80
  79. data/lib/startback/web/health_check.rb +0 -49
  80. data/lib/startback/web/magic_assets/ng_html_transformer.rb +0 -80
  81. data/lib/startback/web/magic_assets/rake_tasks.rb +0 -64
  82. data/lib/startback/web/magic_assets.rb +0 -98
  83. data/lib/startback/web/middleware.rb +0 -13
  84. data/lib/startback/web/prometheus.rb +0 -16
  85. data/lib/startback/web/shield.rb +0 -58
  86. data/lib/startback.rb +0 -43
  87. data/spec/unit/audit/test_prometheus.rb +0 -72
  88. data/spec/unit/audit/test_trailer.rb +0 -105
  89. data/spec/unit/caching/test_entity_cache.rb +0 -136
  90. data/spec/unit/context/test_abstraction_factory.rb +0 -64
  91. data/spec/unit/context/test_dup.rb +0 -42
  92. data/spec/unit/context/test_fork.rb +0 -37
  93. data/spec/unit/context/test_h_factory.rb +0 -31
  94. data/spec/unit/context/test_middleware.rb +0 -45
  95. data/spec/unit/context/test_with_world.rb +0 -20
  96. data/spec/unit/context/test_world.rb +0 -17
  97. data/spec/unit/event/bus/memory/test_async.rb +0 -43
  98. data/spec/unit/event/bus/memory/test_sync.rb +0 -43
  99. data/spec/unit/support/hooks/test_after_hook.rb +0 -54
  100. data/spec/unit/support/hooks/test_before_hook.rb +0 -54
  101. data/spec/unit/support/operation_runner/test_around_run.rb +0 -156
  102. data/spec/unit/support/operation_runner/test_before_after_call.rb +0 -48
  103. data/spec/unit/support/test_data_object.rb +0 -156
  104. data/spec/unit/support/test_env.rb +0 -75
  105. data/spec/unit/support/test_robusteness.rb +0 -229
  106. data/spec/unit/support/test_transaction_manager.rb +0 -64
  107. data/spec/unit/support/test_world.rb +0 -72
  108. data/spec/unit/test_event.rb +0 -62
  109. data/spec/unit/test_operation.rb +0 -55
  110. data/spec/unit/test_support.rb +0 -40
  111. data/spec/unit/web/fixtures/assets/app/hello.es6 +0 -4
  112. data/spec/unit/web/fixtures/assets/app/hello.html +0 -1
  113. data/spec/unit/web/fixtures/assets/index.es6 +0 -1
  114. data/spec/unit/web/test_api.rb +0 -82
  115. data/spec/unit/web/test_auto_caching.rb +0 -81
  116. data/spec/unit/web/test_catch_all.rb +0 -77
  117. data/spec/unit/web/test_cors_headers.rb +0 -88
  118. data/spec/unit/web/test_healthcheck.rb +0 -59
  119. data/spec/unit/web/test_magic_assets.rb +0 -82
@@ -1,162 +0,0 @@
1
- require 'bunny'
2
- module Startback
3
- class Event
4
- class Bus
5
- module Bunny
6
- #
7
- # Asynchronous implementation of the bus abstraction, on top of RabbitMQ
8
- # and using the 'bunny' gem (you need to include it in your Gemfile
9
- # yourself: it is NOT a startback official dependency).
10
- #
11
- # This bus implementation emits events by dumping them to RabbitMQ using
12
- # the event type as exchange name. Listeners may use the `processor`
13
- # parameter to specify the queue name ; otherwise a default "main" queue
14
- # is used.
15
- #
16
- # Examples:
17
- #
18
- # # Connects to RabbitMQ using all default options
19
- # #
20
- # # Uses the STARTBACK_BUS_BUNNY_ASYNC_URL environment variable for
21
- # # connection URL if present.
22
- # Startback::Bus::Bunny::Async.new
23
- #
24
- # # Connects to RabbitMQ using a specific URL
25
- # Startback::Bus::Bunny::Async.new("amqp://rabbituser:rabbitpass@192.168.17.17")
26
- # Startback::Bus::Bunny::Async.new(url: "amqp://rabbituser:rabbitpass@192.168.17.17")
27
- #
28
- # # Connects to RabbitMQ using specific connection options. See Bunny's own
29
- # # documentation
30
- # Startback::Bus::Bunny::Async.new({
31
- # connection_options: {
32
- # host: "192.168.17.17"
33
- # }
34
- # })
35
- #
36
- class Async
37
- include Support::Robustness
38
-
39
- CHANNEL_KEY = 'Startback::Bus::Bunny::Async::ChannelKey'
40
-
41
- DEFAULT_OPTIONS = {
42
- # (optional) The URL to use for connecting to RabbitMQ.
43
- url: ENV['STARTBACK_BUS_BUNNY_ASYNC_URL'],
44
-
45
- # (optional) The options has to pass to ::Bunny constructor
46
- connection_options: nil,
47
-
48
- # (optional) The options to use for the emitter/listener fanout
49
- fanout_options: {},
50
-
51
- # (optional) The options to use for the listener queue
52
- queue_options: {},
53
-
54
- # (optional) Default event factory to use, if any
55
- event_factory: nil,
56
-
57
- # (optional) A default context to use for general logging
58
- context: nil,
59
-
60
- # (optional) Size of consumer pool
61
- consumer_pool_size: 1,
62
-
63
- # (optional) Whether the program must be aborted on consumption
64
- # error
65
- abort_on_exception: true,
66
-
67
- # (optional) Whether connection occurs immediately,
68
- # or on demand later
69
- autoconnect: false
70
- }
71
-
72
- # Creates a bus instance, using the various options provided to
73
- # fine-tune behavior.
74
- def initialize(options = {})
75
- options = { url: options } if options.is_a?(String)
76
- @options = DEFAULT_OPTIONS.merge(options)
77
- connect if @options[:autoconnect]
78
- end
79
- attr_reader :options
80
-
81
- def connect
82
- disconnect
83
- conn = options[:connection_options] || options[:url]
84
- try_max_times(10) do
85
- @bunny = ::Bunny.new(conn)
86
- @bunny.start
87
- channel # make sure we already create the channel
88
- log(:info, {op: "#{self.class.name}#connect", op_data: conn}, options[:context])
89
- end
90
- end
91
-
92
- def disconnect
93
- if channel = Thread.current[CHANNEL_KEY]
94
- channel.close
95
- Thread.current[CHANNEL_KEY] = nil
96
- end
97
- @bunny.close if @bunny
98
- end
99
-
100
- def channel
101
- unless @bunny
102
- raise Startback::Errors::Error, "Please connect your bus first, or use autoconnect: true"
103
- end
104
-
105
- Thread.current[CHANNEL_KEY] ||= @bunny.create_channel(
106
- nil,
107
- consumer_pool_size, # consumer_pool_size
108
- abort_on_exception? # consumer_pool_abort_on_exception
109
- )
110
- end
111
-
112
- def emit(event)
113
- stop_errors(self, "emit", event.context) do
114
- fanout = channel.fanout(event.type.to_s, fanout_options)
115
- fanout.publish(event.to_json)
116
- end
117
- end
118
-
119
- def listen(type, processor = nil, listener = nil, &bl)
120
- raise ArgumentError, "A listener must be provided" unless listener || bl
121
-
122
- fanout = channel.fanout(type.to_s, fanout_options)
123
- queue = channel.queue((processor || "main").to_s, queue_options)
124
- queue.bind(fanout)
125
- queue.subscribe do |delivery_info, properties, body|
126
- stop_errors(self, "listen") do
127
- (listener || bl).call(body)
128
- end
129
- end
130
- end
131
-
132
- protected
133
-
134
- def consumer_pool_size
135
- options[:consumer_pool_size]
136
- end
137
-
138
- def abort_on_exception?
139
- options[:abort_on_exception]
140
- end
141
-
142
- def fanout_options
143
- options[:fanout_options]
144
- end
145
-
146
- def queue_options
147
- options[:queue_options]
148
- end
149
-
150
- def factor_event(body)
151
- if options[:event_factory]
152
- options[:event_factory].call(body)
153
- else
154
- Event.json(body, options)
155
- end
156
- end
157
-
158
- end # class Async
159
- end # module Bunny
160
- end # class Bus
161
- end # class Event
162
- end # module Startback
@@ -1 +0,0 @@
1
- require_relative 'bunny/async'
@@ -1,45 +0,0 @@
1
- module Startback
2
- class Event
3
- class Bus
4
- module Memory
5
- #
6
- # Asynchronous implementation of the Bus abstraction, for use between
7
- # components sharing the same process.
8
- #
9
- # This implementation actually calls listeners synchronously (it mays)
10
- # but hides error raised by them. See Bus::Bunny::Async for another
11
- # implementation that is truly asynchronous and relies on RabbitMQ.
12
- #
13
- class Async
14
- include Support::Robustness
15
-
16
- DEFAULT_OPTIONS = {
17
- }
18
-
19
- def initialize(options = {})
20
- @options = DEFAULT_OPTIONS.merge(options)
21
- @listeners = {}
22
- end
23
-
24
- def connect
25
- end
26
-
27
- def emit(event)
28
- (@listeners[event.type.to_s] || []).each do |l|
29
- stop_errors(self, "emit", event) {
30
- l.call(event)
31
- }
32
- end
33
- end
34
-
35
- def listen(type, processor = nil, listener = nil, &bl)
36
- raise ArgumentError, "A listener must be provided" unless listener || bl
37
- @listeners[type.to_s] ||= []
38
- @listeners[type.to_s] << (listener || bl)
39
- end
40
-
41
- end # class Sync
42
- end # module Memory
43
- end # class Bus
44
- end # class Event
45
- end # module Startback
@@ -1,35 +0,0 @@
1
- module Startback
2
- class Event
3
- class Bus
4
- module Memory
5
- #
6
- # Synchronous implementation of the Bus abstraction, for use between
7
- # components sharing the same process.
8
- #
9
- class Sync
10
- include Support::Robustness
11
-
12
- def initialize
13
- @listeners = {}
14
- end
15
-
16
- def connect
17
- end
18
-
19
- def emit(event)
20
- (@listeners[event.type.to_s] || []).each do |l|
21
- l.call(event)
22
- end
23
- end
24
-
25
- def listen(type, processor = nil, listener = nil, &bl)
26
- raise ArgumentError, "A listener must be provided" unless listener || bl
27
- @listeners[type.to_s] ||= []
28
- @listeners[type.to_s] << (listener || bl)
29
- end
30
-
31
- end # class Sync
32
- end # module Memory
33
- end # class Bus
34
- end # class Event
35
- end # module Startback
@@ -1,2 +0,0 @@
1
- require_relative 'memory/sync'
2
- require_relative 'memory/async'
@@ -1,100 +0,0 @@
1
- module Startback
2
- class Event
3
- #
4
- # Sync and async bus abstraction allowing to register listeners and
5
- # emitting events towards them.
6
- #
7
- # This bus actually decorates two busses, one in synchronous and the
8
- # other one is asynchronous (optional).
9
- #
10
- # * A synchronous bus MUST call the listeners as part of emitting
11
- # process, and MUST re-raise any error occuring during that process.
12
- # See, e.g. Startback::Bus::Memory::Sync
13
- #
14
- # * An asynchronous bus MAY call the listeners later, but MUST hide
15
- # errors to the emitter.
16
- # See, e.g. Startback::Bus::Memory::Async
17
- #
18
- # This bus facade emits events to both sync and async busses (if any),
19
- # and listen on the sync one by default.
20
- #
21
- # For emitters:
22
- #
23
- # # This will synchronously call every listeners who `listen`
24
- # # on the synchronous bus (& reraise exceptions) then call
25
- # # (possibly later) all listeners who `listen` on the
26
- # # asynchronous bus if any (& hide exceptions).
27
- # bus.emit(event)
28
- #
29
- # # This only reaches sync listeners
30
- # bus.sync.emit(event)
31
- #
32
- # # This only reaches async listeners (an async bus must be set)
33
- # bus.async.emit(event)
34
- #
35
- # Please note that there is currently no way to reach sync listeners
36
- # without having to implement error handling on the emitter side.
37
- #
38
- # For listeners:
39
- #
40
- # # This will listen synchronously and make the emitter fail if
41
- # # anything goes wrong with the callback:
42
- # bus.listen(event_type) do |event|
43
- # ...
44
- # end
45
- #
46
- # # It is a shortcut for:
47
- # bus.sync.listen(event_type) do |event| ... end
48
- #
49
- # This will listen asynchronously and could not make the emitter
50
- # fail if something goes wrong with the callback.
51
- # bus.async.listen(event_type) do |event|
52
- # ...
53
- # end
54
- #
55
- # Feel free to access the sync and async busses directly for specific
56
- # cases though.
57
- #
58
- class Bus
59
- include Support::Robustness
60
-
61
- def initialize(sync = Memory::Sync.new, async = nil)
62
- @sync = sync
63
- @async = async
64
- end
65
- attr_reader :sync, :async
66
-
67
- def connect
68
- sync.connect if sync
69
- async.connect if async
70
- end
71
-
72
- # Emits a particular event to the listeners.
73
- #
74
- # @arg event an event, should be an Event instance (through duck
75
- # typing is allowed)
76
- def emit(event)
77
- monitor({
78
- op: "Startback::Bus#emit",
79
- op_data: {
80
- event: { type: event.type }
81
- }
82
- }, event.context) do
83
- sync.emit(event)
84
- async.emit(event) if async
85
- end
86
- end
87
-
88
- # Registers `listener` as being interested in receiving events of
89
- # a specific type.
90
- #
91
- # @arg type: Symbol, the type of event the listener is interested in.
92
- # @arg listener: Proc, the listener itself.
93
- def listen(type, processor = nil, listener = nil, &bl)
94
- sync.listen(type, processor, listener, &bl)
95
- end
96
-
97
- end # class Bus
98
- end # class Event
99
- end # module Startback
100
- require_relative 'bus/memory'
@@ -1,94 +0,0 @@
1
- require 'rack'
2
- require 'startback'
3
- module Startback
4
- class Event
5
- #
6
- # This class is the starting point of event handling in
7
- # Startback. It holds a Bus instance to which emitters
8
- # and listeners can connect.
9
- #
10
- # The Engine exposes a rack app (.rack_app) with a /healthcheck webservice.
11
- # It is supposed to be mounted to a webserver such as puma.
12
- #
13
- # This class goes hand in hand with the `startback:engine`
14
- # docker image. It can be extended by subclasses to override
15
- # the following methods:
16
- #
17
- # - bus to use something else than a simple memory bus
18
- # - on_health_check to check specific health conditions
19
- # - create_agents to instantiate all listening agents
20
- # (unless auto_create_agents is used)
21
- # - rack_app if you want to customize the API running
22
- #
23
- class Engine
24
- include Support::Robustness
25
-
26
- DEFAULT_OPTIONS = {
27
-
28
- }
29
-
30
- def initialize(options = {}, context = Context.new)
31
- @options = DEFAULT_OPTIONS.merge(options)
32
- @context = context
33
- @context.engine = self
34
- end
35
- attr_reader :options, :context
36
-
37
- class << self
38
- def auto_create_agents?
39
- !!@auto_create_agents
40
- end
41
-
42
- # Register a base class which will be used to discover
43
- # the agents to start when the engine is ran.
44
- def auto_create_agents(base_class = nil)
45
- @auto_create_agents ||= base_class
46
- @auto_create_agents
47
- end
48
- end
49
-
50
- # This method is executed on health check and can be
51
- # overriden by subclasses to perform specific checks.
52
- def on_health_check
53
- "Ok"
54
- end
55
-
56
- def bus
57
- @bus ||= ::Startback::Event::Bus.new
58
- end
59
-
60
- def connect
61
- log(:info, self, "Connecting to the bus now!")
62
- bus.connect
63
- end
64
-
65
- def create_agents
66
- return unless parent = self.class.auto_create_agents
67
-
68
- ObjectSpace
69
- .each_object(Class)
70
- .select { |klass| klass <= parent }
71
- .each { |klass| klass.new(self) }
72
- end
73
-
74
- def factor_event(event_data)
75
- Event.json(event_data, context)
76
- end
77
-
78
- def rack_app
79
- engine = self
80
- Rack::Builder.new do
81
- use Startback::Web::CatchAll
82
-
83
- map '/health-check' do
84
- health = Startback::Web::HealthCheck.new {
85
- engine.on_health_check
86
- }
87
- run(health)
88
- end
89
- end
90
- end
91
-
92
- end # class Engine
93
- end # class Event
94
- end # module Startback
@@ -1,5 +0,0 @@
1
- module Startback
2
- class Context
3
- attr_accessor :engine
4
- end # class Context
5
- end # module Startback
@@ -1,13 +0,0 @@
1
- module Startback
2
- class Operation
3
-
4
- def self.emits(type, &bl)
5
- after_call do
6
- event_data = instance_exec(&bl)
7
- event = type.new(type.to_s, event_data, context)
8
- context.engine.bus.emit(event)
9
- end
10
- end
11
-
12
- end # class Operation
13
- end # module Startback
@@ -1,47 +0,0 @@
1
- module Startback
2
- #
3
- # An Event occuring a given context and having a type and attached data.
4
- #
5
- # Event instances have String types that are by default unrelated to ruby
6
- # classes. Also, this Event class has a `json` information contract that
7
- # allows dumping & reloading them easily. A context or context_factory may
8
- # be provided in dress world to reload the event context from data, but
9
- # that logic is opaque to this class.
10
- #
11
- # This class is intended to be subclassed if a more specific event protocol
12
- # is wanted.
13
- #
14
- class Event
15
-
16
- def initialize(type, data, context = nil)
17
- @type = type.to_s
18
- @data = OpenStruct.new(data)
19
- @context = context
20
- end
21
- attr_reader :context, :type, :data
22
-
23
- def self.json(src, context)
24
- return src if src.is_a?(Event)
25
-
26
- parsed = JSON.parse(src)
27
- klass = Kernel.const_get(parsed['type'])
28
- context = context.fork(parsed['context']) if context
29
- klass.new(parsed['type'], parsed['data'], context)
30
- end
31
-
32
- def to_json(*args, &bl)
33
- h = {
34
- type: self.type,
35
- data: data.to_h
36
- }
37
- h[:context] = context if context
38
- h.to_json(*args, &bl)
39
- end
40
-
41
- end # class Event
42
- end # module Startback
43
- require_relative 'event/ext/context'
44
- require_relative 'event/ext/operation'
45
- require_relative 'event/agent'
46
- require_relative 'event/bus'
47
- require_relative 'event/engine'
@@ -1,9 +0,0 @@
1
- class DateTime
2
-
3
- # Makes sure that DateTime are exported with ISO8601
4
- # conventions when using to_json and to_csv
5
- def to_s(*args)
6
- iso8601
7
- end
8
-
9
- end
@@ -1,9 +0,0 @@
1
- class Time
2
-
3
- # Makes sure that Time are exported with ISO8601
4
- # conventions when using to_json and to_csv
5
- def to_s(*args)
6
- iso8601
7
- end
8
-
9
- end
@@ -1,6 +0,0 @@
1
- module Startback
2
- class Model
3
- include Support::DataObject
4
-
5
- end # class Model
6
- end # module Startback
@@ -1,19 +0,0 @@
1
- module Startback
2
- class Operation
3
- class ErrorOperation < Operation
4
-
5
- def initialize(details)
6
- @details = details
7
- end
8
- attr_reader :details
9
-
10
- def call
11
- end
12
-
13
- def bind(world)
14
- self
15
- end
16
-
17
- end # class ErrorOperation
18
- end # class Operation
19
- end # module Startback
@@ -1,28 +0,0 @@
1
- module Startback
2
- class Operation
3
- class MultiOperation < Operation
4
-
5
- def initialize(ops = [])
6
- @ops = ops
7
- end
8
- attr_reader :ops
9
-
10
- def size
11
- ops.size
12
- end
13
-
14
- def +(other)
15
- MultiOperation.new(@ops + Array(other))
16
- end
17
-
18
- def bind(world)
19
- MultiOperation.new(ops.map{|op| op.bind(world) })
20
- end
21
-
22
- def call
23
- ops.map{|op| op.call }
24
- end
25
-
26
- end # class MultiOperation
27
- end # class Operation
28
- end # module Startback
@@ -1,78 +0,0 @@
1
- module Startback
2
- #
3
- # High-level Operation abstraction, that is a piece of code that executes
4
- # on demand and (generally) changes the state of the software system.
5
- #
6
- # An operation is basically an object that respond to `call`, but that
7
- # executes within a given world (see `bind`). It also has before and
8
- # after hooks that allows specifying what needs to be done before invoking
9
- # call and after having invoked it. All this protocol is actually under
10
- # the responsibility of an `OperationRunner`. Operations should not be
11
- # called manually by third-party code.
12
- #
13
- # Example:
14
- #
15
- # class SayHello < Startback::Operation
16
- #
17
- # before_call do
18
- # # e.g. check_some_permissions
19
- # end
20
- #
21
- # def call
22
- # puts "Hello"
23
- # end
24
- #
25
- # after_call do
26
- # # e.g. log and/or emit something on a bus
27
- # end
28
- #
29
- # end
30
- #
31
- class Operation
32
- extend Support::TransactionPolicy
33
- include Errors
34
- include Support::OperationRunner
35
- include Support::Hooks.new(:call)
36
-
37
- attr_accessor :world
38
- protected :world=
39
-
40
- def initialize(input = {})
41
- @input = input
42
- end
43
- attr_reader :input
44
-
45
- def bind(world)
46
- return self unless world
47
- self.world = world
48
- self
49
- end
50
-
51
- def method_missing(name, *args, &bl)
52
- return super unless args.empty? and bl.nil?
53
- return super unless world
54
- world.fetch(name){ super }
55
- end
56
-
57
- def respond_to?(name, *args)
58
- super || (world && world.has_key?(name))
59
- end
60
-
61
- def with_context(ctx = nil)
62
- old_world = self.world
63
- self.world = self.world.merge(context: ctx || old_world.context.dup)
64
- result = ctx ? yield : yield(self.world.context)
65
- self.world = old_world
66
- result
67
- end
68
-
69
- protected
70
-
71
- def operation_world(op)
72
- self.world
73
- end
74
-
75
- end # class Operation
76
- end # module Startback
77
- require_relative 'operation/error_operation'
78
- require_relative 'operation/multi_operation'
@@ -1,11 +0,0 @@
1
- module Startback
2
- class Services
3
- include Startback::Errors
4
-
5
- def initialize(context)
6
- @context = context
7
- end
8
- attr_reader :context
9
-
10
- end # class Services
11
- end # module Startback