startback 0.12.0 → 0.12.3

Sign up to get free protection for your applications and to get access to all the features.
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