startback 0.12.0 → 0.12.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 67ffd7abceaf1b4e048cc8f02f668b682ea81f62fc7de5228a9f0d12abab1df8
4
- data.tar.gz: 1eb075bdec30a569726bc3f2a74c1ce427aef8ff0c3cbcee401a61c034e71ca6
3
+ metadata.gz: 402d175b50a47cda7b683e91613fa0b15405ba0415b1d4b27c765f087717951e
4
+ data.tar.gz: 6b926b4b805ca0623cd66f37a80802d0eb9a41a44707be1952d8cb4f328314ee
5
5
  SHA512:
6
- metadata.gz: 8cb4d6f1302a34cab267c836c1e0d81c54267607de7f24d350183ff05a79af7cc216a6f34bc96c0e1204f71cca1de744fde448590e99bd96a1ab45c15c8ceddf
7
- data.tar.gz: fecf573e39eb04317d756414349d94092f24a07210629a55347191ef74ec94fcc8079f8a4f38b6c58bf94be5c59fbd79a90a168a4925819ce771269ccae6e3da
6
+ metadata.gz: 7c5093716de177a26401e82cb90d5b596696b11ff3b5ce390b7deae7eba67f3e939b8fa1c1594fea3ad866e7d05d364fbc6243428b8cf378573ddbe6843052c3
7
+ data.tar.gz: 24ec0a98d2374cb78130df5358909a4715ee7f7a5e4ec6685a136bc67b03ea8eaff26b0d2f6a52cbd19219145d034a6b95c8147dbe11aa64549a195ff0f81990
@@ -18,7 +18,7 @@ module Startback
18
18
  #
19
19
  # # Use a user defined context class
20
20
  # Rack::Builder.new do
21
- # use Startback::Context::Middleware, context_class: MyContextClass
21
+ # use Startback::Context::Middleware, MyContextClass.new
22
22
  #
23
23
  # run ->(env){
24
24
  # ctx = env[Startback::Context::Middleware::RACK_ENV_KEY]
@@ -31,18 +31,14 @@ module Startback
31
31
 
32
32
  RACK_ENV_KEY = 'SAMBACK_CONTEXT'
33
33
 
34
- DEFAULT_OPTIONS = {
35
- context_class: Context
36
- }
37
-
38
- def initialize(app, options = {})
34
+ def initialize(app, context = Context.new)
39
35
  @app = app
40
- @options = DEFAULT_OPTIONS.merge(options || {})
36
+ @context = context
41
37
  end
42
- attr_reader :options
38
+ attr_reader :context
43
39
 
44
40
  def call(env)
45
- env[RACK_ENV_KEY] ||= options[:context_class].h({}).tap{|c|
41
+ env[RACK_ENV_KEY] ||= context.dup.tap{|c|
46
42
  c.original_rack_env = env.dup
47
43
  }
48
44
  @app.call(env)
@@ -112,6 +112,13 @@ module Startback
112
112
  to_h.to_json(*args, &bl)
113
113
  end
114
114
 
115
+ def fork(h = nil)
116
+ dup.tap{|duped|
117
+ self.class.h_factor!(duped, h) if h
118
+ yield(duped) if block_given?
119
+ }
120
+ end
121
+
115
122
  def dup
116
123
  super.tap{|c|
117
124
  c.send(:clean_factored!)
@@ -16,9 +16,12 @@ module Startback
16
16
 
17
17
  def initialize(engine)
18
18
  @engine = engine
19
+ @context = nil
19
20
  install_listeners
20
21
  end
21
22
  attr_reader :engine
23
+ attr_accessor :context
24
+ protected :context=
22
25
 
23
26
  protected
24
27
 
@@ -38,8 +41,9 @@ module Startback
38
41
  #
39
42
  # See Bus#listen
40
43
  def async(exchange, queue)
41
- bus.async.listen(exchange, queue) do |event|
42
- dup.call(event)
44
+ bus.async.listen(exchange, queue) do |event_data|
45
+ event = engine.factor_event(event_data)
46
+ with_context(event.context).call(event)
43
47
  end
44
48
  end
45
49
 
@@ -47,8 +51,9 @@ module Startback
47
51
  #
48
52
  # See Bus#listen
49
53
  def sync(exchange, queue)
50
- bus.listen(exchange, queue) do |event|
51
- dup.call(event)
54
+ bus.listen(exchange, queue) do |event_data|
55
+ event = engine.factor_event(event_data)
56
+ with_context(event.context).call(event)
52
57
  end
53
58
  end
54
59
 
@@ -66,6 +71,14 @@ module Startback
66
71
  raise NotImplementedError
67
72
  end
68
73
 
74
+ def with_context(context)
75
+ dup.tap{|a| a.send(:context=, context) }
76
+ end
77
+
78
+ def operation_world(op)
79
+ super(op).merge(context: ctx)
80
+ end
81
+
69
82
  end # class Agent
70
83
  end # class Event
71
84
  end # module Starback
@@ -123,11 +123,8 @@ module Startback
123
123
  queue = channel.queue((processor || "main").to_s, queue_options)
124
124
  queue.bind(fanout)
125
125
  queue.subscribe do |delivery_info, properties, body|
126
- event = stop_errors(self, "listen") do
127
- factor_event(body)
128
- end
129
- stop_errors(self, "listen", event.context) do
130
- (listener || bl).call(event)
126
+ stop_errors(self, "listen") do
127
+ (listener || bl).call(body)
131
128
  end
132
129
  end
133
130
  end
@@ -36,6 +36,7 @@ module Startback
36
36
  def initialize(options = {}, context = Context.new)
37
37
  @options = DEFAULT_OPTIONS.merge(options)
38
38
  @context = context
39
+ @context.engine = self
39
40
  end
40
41
  attr_reader :options, :context
41
42
 
@@ -84,6 +85,10 @@ module Startback
84
85
  .each { |klass| klass.new(self) }
85
86
  end
86
87
 
88
+ def factor_event(event_data)
89
+ Event.json(event_data, context)
90
+ end
91
+
87
92
  class Runner
88
93
 
89
94
  DEFAULT_SERVER_ENGINE_OPTIONS = {
@@ -0,0 +1,5 @@
1
+ module Startback
2
+ class Context
3
+ attr_accessor :engine
4
+ end # class Context
5
+ end # module Startback
@@ -0,0 +1,13 @@
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
@@ -20,14 +20,13 @@ module Startback
20
20
  end
21
21
  attr_reader :context, :type, :data
22
22
 
23
- def self.json(src, world = {})
23
+ def self.json(src, context)
24
+ return src if src.is_a?(Event)
25
+
24
26
  parsed = JSON.parse(src)
25
- context = if world[:context]
26
- world[:context]
27
- elsif world[:context_factory]
28
- world[:context_factory].call(parsed)
29
- end
30
- Event.new(parsed['type'], parsed['data'], context)
27
+ klass = Kernel.const_get(parsed['type'])
28
+ context = context.fork(parsed['context']) if context
29
+ klass.new(parsed['type'], parsed['data'], context)
31
30
  end
32
31
 
33
32
  def to_json(*args, &bl)
@@ -41,6 +40,8 @@ module Startback
41
40
 
42
41
  end # class Event
43
42
  end # module Startback
43
+ require_relative 'event/ext/context'
44
+ require_relative 'event/ext/operation'
44
45
  require_relative 'event/agent'
45
46
  require_relative 'event/bus'
46
47
  require_relative 'event/engine'
@@ -2,7 +2,7 @@ module Startback
2
2
  module Version
3
3
  MAJOR = 0
4
4
  MINOR = 12
5
- TINY = 0
5
+ TINY = 3
6
6
  end
7
7
  VERSION = "#{Version::MAJOR}.#{Version::MINOR}.#{Version::TINY}"
8
8
  end
data/spec/spec_helper.rb CHANGED
@@ -10,3 +10,28 @@ end
10
10
  RSpec.configure do |c|
11
11
  c.include SpecHelpers
12
12
  end
13
+
14
+ class SubContext < Startback::Context
15
+ attr_accessor :foo
16
+ h_factory do |c,h|
17
+ c.foo = h["foo"]
18
+ end
19
+ h_dump do |h|
20
+ h.merge!("foo" => foo)
21
+ end
22
+ end
23
+
24
+ class SubContext
25
+ attr_accessor :bar
26
+ h_factory do |c,h|
27
+ c.bar = h["bar"]
28
+ end
29
+ h_dump do |h|
30
+ h.merge!("bar" => bar)
31
+ end
32
+ end
33
+
34
+ class User
35
+ class Changed < Startback::Event
36
+ end
37
+ end
@@ -3,12 +3,8 @@ require 'spec_helper'
3
3
  module Startback
4
4
  describe Context, "dup" do
5
5
 
6
- class Subcontext < Context
7
- attr_accessor :foo
8
- end
9
-
10
6
  let(:context) {
11
- Subcontext.new.tap{|s| s.foo = "bar" }
7
+ SubContext.new.tap{|s| s.foo = "bar" }
12
8
  }
13
9
 
14
10
  class ContextRelatedAbstraction
@@ -27,7 +23,7 @@ module Startback
27
23
  expect(x).not_to be(context)
28
24
  }
29
25
  expect(seen).to be(got)
30
- expect(got).to be_a(Subcontext)
26
+ expect(got).to be_a(SubContext)
31
27
  expect(got).not_to be(context)
32
28
  expect(got.foo).to eql("bar")
33
29
  end
@@ -43,4 +39,4 @@ module Startback
43
39
  end
44
40
 
45
41
  end
46
- end
42
+ end
@@ -0,0 +1,38 @@
1
+ require 'spec_helper'
2
+
3
+ module Startback
4
+ describe Context, "fork" do
5
+
6
+ it 'is a simple dup without args' do
7
+ context = SubContext.new
8
+ context.foo = ['hello']
9
+
10
+ forked = context.fork
11
+ puts "Forked: #{forked.inspect}"
12
+ expect(fork).not_to be(context)
13
+ expect(forked.foo).to eql(['hello'])
14
+ expect(forked.foo).to be(context.foo)
15
+ end
16
+
17
+ it 'yields the context if a block is provided' do
18
+ context = SubContext.new
19
+
20
+ seen = false
21
+ context.fork({ 'foo' => 'hello' }) do |forked|
22
+ expect(fork).not_to be(context)
23
+ expect(forked.foo).to eql('hello')
24
+ seen = true
25
+ end
26
+ expect(seen).to eql(true)
27
+ end
28
+
29
+ it 'uses the factory on the hash provided' do
30
+ context = SubContext.new
31
+
32
+ forked = context.fork({ 'foo' => 'hello' })
33
+ expect(fork).not_to be(context)
34
+ expect(forked.foo).to eql('hello')
35
+ end
36
+
37
+ end
38
+ end
@@ -7,26 +7,6 @@ module Startback
7
7
  expect(Context.new.to_json).to eql("{}")
8
8
  end
9
9
 
10
- class SubContext < Context
11
- attr_accessor :foo
12
- h_factory do |c,h|
13
- c.foo = h["foo"]
14
- end
15
- h_dump do |h|
16
- h.merge!("foo" => foo)
17
- end
18
- end
19
-
20
- class SubContext
21
- attr_accessor :bar
22
- h_factory do |c,h|
23
- c.bar = h["bar"]
24
- end
25
- h_dump do |h|
26
- h.merge!("bar" => bar)
27
- end
28
- end
29
-
30
10
  it 'allows installing factories' do
31
11
  expect(Context.h_factories).to be_empty
32
12
  expect(SubContext.h_factories.size).to eql(2)
@@ -10,18 +10,18 @@ module Startback
10
10
  include Rack::Test::Methods
11
11
 
12
12
  def app
13
- opts = middleware_options
13
+ build_args = self.build_args
14
14
  Rack::Builder.new do
15
- use Middleware, opts
15
+ use Middleware, *build_args
16
16
  run ->(env){
17
- ctx = env[Startback::Context::Middleware::RACK_ENV_KEY]
17
+ ctx = env[Startback::Context::Middleware::RACK_ENV_KEY]
18
18
  [200, {}, ctx.class.to_s]
19
19
  }
20
20
  end
21
21
  end
22
22
 
23
- context 'when used without option' do
24
- let(:middleware_options){ nil }
23
+ context 'when used without context' do
24
+ let(:build_args){ [] }
25
25
 
26
26
  it 'sets the default context class' do
27
27
  get '/'
@@ -31,9 +31,7 @@ module Startback
31
31
  end
32
32
 
33
33
  context 'when specifying the context class' do
34
- let(:middleware_options){{
35
- context_class: MyContextSubClass
36
- }}
34
+ let(:build_args){ [MyContextSubClass.new] }
37
35
 
38
36
  it 'sets the default context class' do
39
37
  get '/'
@@ -4,7 +4,7 @@ module Startback
4
4
  describe Event do
5
5
 
6
6
  subject{
7
- Event.new("user_changed", { "foo" => "bar" })
7
+ Event.new("User::Changed", { "foo" => "bar" })
8
8
  }
9
9
 
10
10
  it 'presents an ostruct on top of its data' do
@@ -15,7 +15,7 @@ module Startback
15
15
 
16
16
  JSON_SRC = <<-JSON.gsub(/\s+/, "")
17
17
  {
18
- "type": "user_changed",
18
+ "type": "User::Changed",
19
19
  "data": {
20
20
  "foo": "bar"
21
21
  }
@@ -27,10 +27,10 @@ module Startback
27
27
  end
28
28
 
29
29
  it 'has a to_json that dumps the context if any' do
30
- evt = Event.new("user_changed", { "foo" => "bar" }, { "baz": "context" })
30
+ evt = Event.new("User::Changed", { "foo" => "bar" }, { "baz": "context" })
31
31
  expect(evt.to_json).to eql(<<-JSON.gsub(/\s+/, ""))
32
32
  {
33
- "type": "user_changed",
33
+ "type": "User::Changed",
34
34
  "data": {
35
35
  "foo": "bar"
36
36
  },
@@ -43,26 +43,19 @@ module Startback
43
43
 
44
44
 
45
45
  it 'has a json class method that works as expected' do
46
- evt = Event.json(JSON_SRC)
46
+ evt = Event.json(JSON_SRC, nil)
47
47
  expect(evt).to be_a(Event)
48
- expect(evt.type).to eql("user_changed")
48
+ expect(evt.type).to eql("User::Changed")
49
49
  expect(evt.data).to eql(subject.data)
50
50
  end
51
51
 
52
- it 'accepts an explicit context in the world' do
53
- evt = Event.json(JSON_SRC, context: 12)
54
- expect(evt.context).to eql(12)
52
+ it 'accepts an explicit context as second argument' do
53
+ c = SubContext.new.tap{|x| x.foo = 'hello' }
54
+ evt = Event.json(JSON_SRC, c)
55
+ expect(evt.context).not_to be(c)
56
+ expect(evt.context).to be_a(SubContext)
57
+ expect(evt.context.foo).to eql('hello')
55
58
  end
56
-
57
- it 'accepts an context factory in the world' do
58
- cf = ->(arg) {
59
- expect(arg).to eql(JSON.parse(JSON_SRC))
60
- 12
61
- }
62
- evt = Event.json(JSON_SRC, context_factory: cf)
63
- expect(evt.context).to eql(12)
64
- end
65
-
66
59
  end
67
60
 
68
61
  end
@@ -53,7 +53,7 @@ module Startback
53
53
 
54
54
  def app
55
55
  Rack::Builder.new do
56
- use Context::Middleware, context_class: MyContextWithErrorHandler
56
+ use Context::Middleware, MyContextWithErrorHandler.new
57
57
  use CatchAll
58
58
  run ->(env){ raise AnError, "Hello error" }
59
59
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: startback
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.12.0
4
+ version: 0.12.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bernard Lambeau
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-05-19 00:00:00.000000000 Z
11
+ date: 2022-05-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec
@@ -400,6 +400,8 @@ files:
400
400
  - lib/startback/event/bus/memory/async.rb
401
401
  - lib/startback/event/bus/memory/sync.rb
402
402
  - lib/startback/event/engine.rb
403
+ - lib/startback/event/ext/context.rb
404
+ - lib/startback/event/ext/operation.rb
403
405
  - lib/startback/ext.rb
404
406
  - lib/startback/ext/date_time.rb
405
407
  - lib/startback/ext/time.rb
@@ -434,6 +436,7 @@ files:
434
436
  - spec/unit/caching/test_entity_cache.rb
435
437
  - spec/unit/context/test_abstraction_factory.rb
436
438
  - spec/unit/context/test_dup.rb
439
+ - spec/unit/context/test_fork.rb
437
440
  - spec/unit/context/test_h_factory.rb
438
441
  - spec/unit/context/test_middleware.rb
439
442
  - spec/unit/event/bus/memory/test_async.rb