light-service 0.15.0 → 0.16.0

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: f400829da41766f56e7f0cb9cfe95aa028ef8ab34bf0bc5794bfafcff3cdcfb1
4
- data.tar.gz: 41dbd504ac39a0804eb445b4af086dbcf9986264077994277e17fde98b7bdc3d
3
+ metadata.gz: d41ecb22a4b0d3cd9779c1e5726c8f34e6f186a34f04ec97ea5928f682f08fd8
4
+ data.tar.gz: 64f4d7f52607048313e9f39bea158899ef804deb32ae9744715e5969cc7b1567
5
5
  SHA512:
6
- metadata.gz: e9a1148b82b6e1a0813400b0d23b013ff6f06965f3204bb3fa95101adc8a749223dd334887f7543622b4a829fd17f190c21dd5f601df3aecde8d8451459a76af
7
- data.tar.gz: f0aec690e94896dcc13d6caa774003e49ddfa6b74c5acf9272fb7b9d3710d28db4a29601e725e3729deba820013c62b740739d5c6052c4c5ae93fd885cec6fda
6
+ metadata.gz: 2345b72e3d9581aecaea2fe5eca1bd3c538cdb0cfcd2d943ac021ca4f3ef31913ac4b06011944c017df330f3ee8dc385793e8185f3e79cba6c51fbe6ee6acba6
7
+ data.tar.gz: 703b9608edfa42bf0d73135fa5b4eafa789e8a31c4239056fd8b7397d6f0a212f8c5c69d66834f1f5b9fe2431b234f8c0373ccaaa86f286d82671bfe8d8b705b
@@ -0,0 +1,28 @@
1
+ name: CI Tests
2
+
3
+ on:
4
+ push:
5
+ branches: [ main ]
6
+ pull_request:
7
+ branches: [ main ]
8
+
9
+ jobs:
10
+ test:
11
+ runs-on: ${{ matrix.os }}-latest
12
+ strategy:
13
+ fail-fast: false
14
+ matrix:
15
+ os: [ubuntu, macos]
16
+ ruby: [2.5.3, 2.6.6, 2.7.2]
17
+ gemfile: [activesupport_5, activesupport_6]
18
+ continue-on-error: ${{ endsWith(matrix.ruby, 'head') || matrix.ruby == 'debug' }}
19
+ env: # $BUNDLE_GEMFILE must be set at the job level, so it is set for all steps
20
+ BUNDLE_GEMFILE: gemfiles/${{ matrix.gemfile }}.gemfile
21
+ steps:
22
+ - uses: actions/checkout@v2
23
+ - uses: ruby/setup-ruby@v1
24
+ with:
25
+ ruby-version: ${{ matrix.ruby }}
26
+ - run: bundle install
27
+ - run: bundle exec rspec spec
28
+ - run: bundle exec rubocop
data/.travis.yml CHANGED
@@ -4,10 +4,9 @@ env:
4
4
  - RUN_COVERAGE_REPORT=true
5
5
 
6
6
  rvm:
7
- - 2.4.2
8
7
  - 2.5.3
9
- - 2.6.0
10
- - 2.7.0
8
+ - 2.6.6
9
+ - 2.7.2
11
10
 
12
11
  before_install:
13
12
  - 'echo ''gem: --no-ri --no-rdoc'' > ~/.gemrc'
@@ -26,9 +25,5 @@ gemfile:
26
25
 
27
26
  matrix:
28
27
  exclude:
29
- - rvm: 2.4.2
30
- gemfile: gemfiles/activesupport_6.gemfile
31
- - rvm: 2.7.0
32
- gemfile: gemfiles/activesupport_3.gemfile
33
- - rvm: 2.7.0
28
+ - rvm: 2.7.2
34
29
  gemfile: gemfiles/activesupport_4.gemfile
data/README.md CHANGED
@@ -1,20 +1,15 @@
1
1
  ![LightService](https://raw.githubusercontent.com/adomokos/light-service/master/resources/light-service.png)
2
2
 
3
3
  [![Gem Version](https://img.shields.io/gem/v/light-service.svg)](https://rubygems.org/gems/light-service)
4
- [![Build Status](https://secure.travis-ci.org/adomokos/light-service.svg)](http://travis-ci.org/adomokos/light-service)
4
+ [![CI Tests](https://github.com/adomokos/light-service/actions/workflows/project-build.yml/badge.svg)](https://github.com/adomokos/light-service/actions/workflows/project-build.yml)
5
5
  [![codecov](https://codecov.io/gh/adomokos/light-service/branch/master/graph/badge.svg)](https://codecov.io/gh/adomokos/light-service)
6
6
  [![Code Climate](https://codeclimate.com/github/adomokos/light-service.svg)](https://codeclimate.com/github/adomokos/light-service)
7
7
  [![License](https://img.shields.io/badge/license-MIT-green.svg)](http://opensource.org/licenses/MIT)
8
8
  [![Download Count](https://ruby-gem-downloads-badge.herokuapp.com/light-service?type=total)](https://rubygems.org/gems/light-service)
9
9
 
10
- <br>
10
+ LightService is a powerful and flexible service skeleton framework with an emphasis on simplicity
11
11
 
12
- ![Orchestrators-Deprecated](resources/orchestrators_deprecated.svg)
13
- <br>Version 0.9.0 deprecates Orchestrators and moves all their functionalities into Organizers. Please check out [this PR](https://github.com/adomokos/light-service/pull/132) to see the changes.
14
-
15
- <br>
16
-
17
- ## Table of Content
12
+ ## Table of Contents
18
13
  * [Why LightService?](#why-lightservice)
19
14
  * [Getting Started](#getting-started)
20
15
  * [Requirements](#requirements)
@@ -31,9 +26,11 @@
31
26
  * [Error Codes](#error-codes)
32
27
  * [Action Rollback](#action-rollback)
33
28
  * [Localizing Messages](#localizing-messages)
34
- * [Orchestrator Logic in Organizers](#orchestrator-logic-in-organizers)
29
+ * [Orchestrating Logic in Organizers](#orchestrating-logic-in-organizers)
35
30
  * [ContextFactory for Faster Action Testing](#contextfactory-for-faster-action-testing)
36
31
  * [Rails support](#rails-support)
32
+ * [Implementations in other languages](#other-implementations)
33
+ * [Contributing](#contributing)
37
34
 
38
35
  ## Why LightService?
39
36
 
@@ -866,9 +863,13 @@ end
866
863
 
867
864
  To get the value of a `fail!` or `succeed!` message, simply call `#message` on the returned context.
868
865
 
869
- ## Orchestrator Logic in Organizers
866
+ ## Orchestrating Logic in Organizers
867
+
868
+ The Organizer - Action combination works really well for simple use cases. However, as business logic gets more complex, or when LightService is used in an ETL workflow, the code that routes the different organizers becomes very complex and imperative.
870
869
 
871
- The Organizer - Action combination works really well for simple use cases. However, as business logic gets more complex, or when LightService is used in an ETL workflow, the code that routes the different organizers becomes very complex and imperative. Let's look at a piece of code that does basic data transformations:
870
+ In the past, this was solved using Orchestrators. As of [Version 0.9.0 Orchestrators have been deprecated](https://github.com/adomokos/light-service/pull/132). All their functionality is now usable directly within Organizers. Read on to understand how to orchestrate workflows from within a single Organizer.
871
+
872
+ Let's look at a piece of code that does basic data transformations:
872
873
 
873
874
  ```ruby
874
875
  class ExtractsTransformsLoadsData
@@ -942,7 +943,7 @@ To take advantage of another organizer or action, you might need to tweak the co
942
943
 
943
944
  Use `with_callback` when you want to execute actions with a deferred and controlled callback. It works similar to a Sax parser, I've used it for processing large files. The advantage of it is not having to keep large amount of data in memory. See [this acceptance test](spec/acceptance/organizer/with_callback_spec.rb) as a working example.
944
945
 
945
- `add_to_context` can add key-value pairs on the fly to the context. This functionality is useful when you need a value injected into the context under a specific key right before the subsequent actions are executed. [This test](spec/acceptance/organizer/add_to_context_spec.rb) describes its functionality.
946
+ `add_to_context` can add key-value pairs on the fly to the context. This functionality is useful when you need a value injected into the context under a specific key right before the subsequent actions are executed. Keys are also made available as accessors on the context object and can be used just like methods exposed via `expects` and `promises`. [This test](spec/acceptance/organizer/add_to_context_spec.rb) describes its functionality.
946
947
 
947
948
  Your action needs a certain key in the context but it's under a different one? Use the function `add_aliases` to alias an existing key in the context under the desired key. Take a look at [this test](spec/acceptance/organizer/add_aliases_spec.rb) to see an example.
948
949
 
@@ -1046,6 +1047,13 @@ them through the context. A stub context will be created in the test file using
1046
1047
 
1047
1048
  When specifying `promises`, specs will be created testing for their existence after executing the action.
1048
1049
 
1050
+ ## Other implementations
1051
+
1052
+ | Language | Repo | Author |
1053
+ | :------- |:------------------------------------------------------------------| :------------------------------------------------------|
1054
+ | Python | [pyservice](https://github.com/adomokos/pyservice) | [@adomokos](https://github.com/adomokos) |
1055
+ | PHP | [light-service](https://github.com/douglasgreyling/light-service) | [@douglasgreyling](https://github.com/douglasgreyling) |
1056
+
1049
1057
  ## Contributing
1050
1058
  1. Fork it
1051
1059
  2. Create your feature branch (`git checkout -b my-new-feature`)
data/RELEASES.md CHANGED
@@ -1,11 +1,16 @@
1
1
  A brief list of new features and changes introduced with the specified version.
2
2
 
3
+ ### 0.16.0
4
+ * [Drop Ruby 2.4 support](https://github.com/adomokos/light-service/pull/207)
5
+ * [Fix callback current action](https://github.com/adomokos/light-service/pull/209)
6
+ * [Add Context accessors](https://github.com/adomokos/light-service/pull/211)
7
+ * [Switched to GH Actions from Travis CI](https://github.com/adomokos/light-service/pull/212)
8
+
3
9
  ### 0.15.0
4
10
  * [Add Rails Generators](https://github.com/adomokos/light-service/pull/194) - LightService actions and organizers can be generated with generators
5
11
  * [Add CodeCov](https://github.com/adomokos/light-service/pull/195) - Upload code coverage report to codecov.io
6
12
  * [Remove ActiveSupport 3 checks](https://github.com/adomokos/light-service/pull/197) - They are unsupported, no need to tests them any more.
7
13
 
8
-
9
14
  ### 0.14.0
10
15
  * [Add 'organized_by' to context](https://github.com/adomokos/light-service/pull/192) - Context now have an #organized_by attribute
11
16
 
@@ -44,6 +44,9 @@ module LightService
44
44
  catch(:jump_when_failed) do
45
45
  call_before_action(action_context)
46
46
  yield(action_context)
47
+
48
+ # Reset the stored action in case it was changed downstream
49
+ action_context.current_action = self
47
50
  call_after_action(action_context)
48
51
  end
49
52
  end
@@ -115,9 +115,9 @@ module LightService
115
115
  end
116
116
 
117
117
  def define_accessor_methods_for_keys(keys)
118
- return if keys.nil?
118
+ return if keys.blank?
119
119
 
120
- keys.each do |key|
120
+ Array(keys).each do |key|
121
121
  next if respond_to?(key.to_sym)
122
122
 
123
123
  define_singleton_method(key.to_s) { fetch(key) }
@@ -111,7 +111,24 @@ module LightService
111
111
  end
112
112
 
113
113
  def reserved_keys
114
- %i[message error_code current_action].freeze
114
+ %i[message error_code current_action organized_by].freeze
115
+ end
116
+ end
117
+
118
+ class ReservedKeysViaOrganizerVerifier < ReservedKeysVerifier
119
+ def initialize(context_data)
120
+ @context = LightService::Context.make(context_data)
121
+ end
122
+
123
+ def violated_keys
124
+ context.keys.map(&:to_sym) & reserved_keys
125
+ end
126
+
127
+ def error_message
128
+ <<~ERR
129
+ reserved keys cannot be added to the context
130
+ reserved key: [#{format_keys(violated_keys)}]
131
+ ERR
115
132
  end
116
133
  end
117
134
  end
@@ -65,9 +65,18 @@ module LightService
65
65
  @logger
66
66
  end
67
67
 
68
- def add_to_context(**args)
69
- args.map do |key, value|
70
- execute(->(ctx) { ctx[key.to_sym] = value })
68
+ # Set the value as a key on the context hash
69
+ # and also create convenience accessors for the keys
70
+ def add_to_context(args)
71
+ Context::ReservedKeysViaOrganizerVerifier.new(args).verify
72
+
73
+ Hash(args).map do |key, value|
74
+ context_key = lambda do |ctx|
75
+ ctx[key.to_sym] = value
76
+ ctx.define_accessor_methods_for_keys(key)
77
+ end
78
+
79
+ execute(context_key)
71
80
  end
72
81
  end
73
82
 
@@ -1,3 +1,3 @@
1
1
  module LightService
2
- VERSION = "0.15.0".freeze
2
+ VERSION = "0.16.0".freeze
3
3
  end
@@ -15,8 +15,9 @@ Gem::Specification.new do |gem|
15
15
  gem.name = "light-service"
16
16
  gem.require_paths = ["lib"]
17
17
  gem.version = LightService::VERSION
18
+ gem.required_ruby_version = '>= 2.5.0'
18
19
 
19
- gem.add_runtime_dependency("activesupport", ">= 3.0.0")
20
+ gem.add_runtime_dependency("activesupport", ">= 4.0.0")
20
21
 
21
22
  gem.add_development_dependency("generator_spec", "~> 0.9.4")
22
23
  gem.add_development_dependency("test-unit", "~> 3.0") # Needed for generator specs.
@@ -65,6 +65,23 @@ RSpec.describe 'Action after_actions' do
65
65
  end
66
66
  end
67
67
 
68
+ context 'with callbacks' do
69
+ it 'ensures the correct :current_action is set' do
70
+ TestDoubles::TestWithCallback.after_actions = [
71
+ lambda do |ctx|
72
+ if ctx.current_action == TestDoubles::IterateCollectionAction
73
+ ctx.total -= 1000
74
+ end
75
+ end
76
+ ]
77
+
78
+ result = TestDoubles::TestWithCallback.call
79
+
80
+ expect(result.counter).to eq(3)
81
+ expect(result.total).to eq(-994)
82
+ end
83
+ end
84
+
68
85
  describe 'after_actions can be appended' do
69
86
  it 'adds to the :_after_actions collection' do
70
87
  TestDoubles::AdditionOrganizer.append_after_actions(
@@ -20,6 +20,20 @@ RSpec.describe LightService::Organizer do
20
20
  end
21
21
  end
22
22
 
23
+ class TestAddToContextReservedWords
24
+ extend LightService::Organizer
25
+
26
+ def self.call(context = LightService::Context.make)
27
+ with(context).reduce(steps)
28
+ end
29
+
30
+ def self.steps
31
+ [
32
+ add_to_context(:message => "yo", "error_code" => "00P5")
33
+ ]
34
+ end
35
+ end
36
+
23
37
  it 'adds items to the context on the fly' do
24
38
  result = TestAddToContext.call
25
39
 
@@ -27,4 +41,17 @@ RSpec.describe LightService::Organizer do
27
41
  expect(result.number).to eq(1)
28
42
  expect(result[:something]).to eq('hello')
29
43
  end
44
+
45
+ it 'adds items to the context as accessors' do
46
+ result = TestAddToContext.call
47
+
48
+ expect(result).to be_success
49
+ expect(result.something).to eq('hello')
50
+ end
51
+
52
+ it "will not add items as accessors when they are reserved" do
53
+ expect { TestAddToContextReservedWords.call }.to \
54
+ raise_error(LightService::ReservedKeysInContextError)
55
+ .with_message(/:message, :error_code/)
56
+ end
30
57
  end
@@ -0,0 +1,28 @@
1
+ require 'spec_helper'
2
+ require 'test_doubles'
3
+
4
+ RSpec.describe LightService::Organizer do
5
+ class TestExecuteWithAddToContext
6
+ extend LightService::Organizer
7
+
8
+ def self.call
9
+ with.reduce(steps)
10
+ end
11
+
12
+ def self.steps
13
+ [
14
+ add_to_context(:greeting => "hello"),
15
+ execute(->(ctx) { ctx.greeting.upcase! })
16
+ ]
17
+ end
18
+ end
19
+
20
+ context "when using context values created by add_to_context" do
21
+ it "is expected to reference them as accessors" do
22
+ result = TestExecuteWithAddToContext.call
23
+
24
+ expect(result).to be_a_success
25
+ expect(result.greeting).to eq "HELLO"
26
+ end
27
+ end
28
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: light-service
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.15.0
4
+ version: 0.16.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Attila Domokos
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-07-28 00:00:00.000000000 Z
11
+ date: 2021-07-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 3.0.0
19
+ version: 4.0.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: 3.0.0
26
+ version: 4.0.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: generator_spec
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -157,6 +157,7 @@ executables: []
157
157
  extensions: []
158
158
  extra_rdoc_files: []
159
159
  files:
160
+ - ".github/workflows/project-build.yml"
160
161
  - ".gitignore"
161
162
  - ".rspec"
162
163
  - ".rubocop.yml"
@@ -168,7 +169,6 @@ files:
168
169
  - README.md
169
170
  - RELEASES.md
170
171
  - Rakefile
171
- - gemfiles/activesupport_4.gemfile
172
172
  - gemfiles/activesupport_5.gemfile
173
173
  - gemfiles/activesupport_6.gemfile
174
174
  - lib/generators/light_service/action_generator.rb
@@ -203,7 +203,6 @@ files:
203
203
  - light-service.gemspec
204
204
  - resources/fail_actions.png
205
205
  - resources/light-service.png
206
- - resources/orchestrators_deprecated.svg
207
206
  - resources/organizer_and_actions.png
208
207
  - resources/skip_actions.png
209
208
  - spec/acceptance/add_numbers_spec.rb
@@ -228,6 +227,7 @@ files:
228
227
  - spec/acceptance/organizer/around_each_with_reduce_if_spec.rb
229
228
  - spec/acceptance/organizer/context_failure_and_skipping_spec.rb
230
229
  - spec/acceptance/organizer/execute_spec.rb
230
+ - spec/acceptance/organizer/execute_with_add_to_context_spec.rb
231
231
  - spec/acceptance/organizer/iterate_spec.rb
232
232
  - spec/acceptance/organizer/reduce_if_spec.rb
233
233
  - spec/acceptance/organizer/reduce_until_spec.rb
@@ -270,7 +270,7 @@ homepage: https://github.com/adomokos/light-service
270
270
  licenses:
271
271
  - MIT
272
272
  metadata: {}
273
- post_install_message:
273
+ post_install_message:
274
274
  rdoc_options: []
275
275
  require_paths:
276
276
  - lib
@@ -278,7 +278,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
278
278
  requirements:
279
279
  - - ">="
280
280
  - !ruby/object:Gem::Version
281
- version: '0'
281
+ version: 2.5.0
282
282
  required_rubygems_version: !ruby/object:Gem::Requirement
283
283
  requirements:
284
284
  - - ">="
@@ -286,7 +286,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
286
286
  version: '0'
287
287
  requirements: []
288
288
  rubygems_version: 3.1.2
289
- signing_key:
289
+ signing_key:
290
290
  specification_version: 4
291
291
  summary: A service skeleton with an emphasis on simplicity
292
292
  test_files:
@@ -312,6 +312,7 @@ test_files:
312
312
  - spec/acceptance/organizer/around_each_with_reduce_if_spec.rb
313
313
  - spec/acceptance/organizer/context_failure_and_skipping_spec.rb
314
314
  - spec/acceptance/organizer/execute_spec.rb
315
+ - spec/acceptance/organizer/execute_with_add_to_context_spec.rb
315
316
  - spec/acceptance/organizer/iterate_spec.rb
316
317
  - spec/acceptance/organizer/reduce_if_spec.rb
317
318
  - spec/acceptance/organizer/reduce_until_spec.rb
@@ -1,7 +0,0 @@
1
- # This file was generated by Appraisal
2
-
3
- source "https://rubygems.org"
4
-
5
- gem "activesupport", "~> 4.0"
6
-
7
- gemspec :path => "../"
@@ -1,10 +0,0 @@
1
- <?xml version="1.0" encoding="utf-8"?>
2
- <svg version="1.1"
3
- xmlns="http://www.w3.org/2000/svg"
4
- xmlns:xlink="http://www.w3.org/1999/xlink"
5
- width="350" height="20"
6
- >
7
- <text font-size="20" x="0" y="20" font-family="Verdana">
8
- <tspan fill="red">Orchestrators are DEPRECATED!</tspan>
9
- </text>
10
- </svg>