akasha 0.2.0 → 0.3.0

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
  SHA1:
3
- metadata.gz: '09372b1685568c249f091ff1bbbf4915bb574b91'
4
- data.tar.gz: 982ef7993d2087b2bd55f424228ba5bdf31d867a
3
+ metadata.gz: 4078cc01d0c132a3b675ed21de42246880643c49
4
+ data.tar.gz: 0562b5f9607dea81f47720c680d3f5517c5190e0
5
5
  SHA512:
6
- metadata.gz: 59730ad9b8f01e86d5fdfd01945fea0586002972571595f03810d7af600f9d864a5d5c22fc1e7092a68067f6fd310c16f825980b8515d71f7933a05f2362dfc1
7
- data.tar.gz: 1fb02d4091efe00a925af1ec4d15990c0cc0c61aaaf64a1c64de36a63dcc3eea3b73465d5e558880ad46393d90146dfb6a788d5e5544f7afcdf68bda67f38d78
6
+ metadata.gz: 114a107b63f0f25d9e21b5a00c8a4277885ca705ff7d324199a89e54004c41f410380608d7ba994e8d2f0e3dab220c8a09443c56ef36bc69c551f061d23b3366
7
+ data.tar.gz: 4ef66f8424b38a10ac6b8b4095e9a42f985babf00966d5e7d8928cc8fd588768cf1ee45baa516fe094a8b717ee560d44e5f5856028aa6af97eee806b88c3c1ca
@@ -1,6 +1,16 @@
1
1
  Style/FrozenStringLiteralComment:
2
2
  Enabled: false
3
+ Metrics/AbcSize:
4
+ Max: 17
5
+ Metrics/BlockLength:
6
+ Exclude:
7
+ - spec/**/*_spec.rb
8
+ - akasha.gemspec
9
+ Metrics/ClassLength:
10
+ Max: 110
3
11
  Metrics/LineLength:
4
12
  Max: 120
5
13
  Metrics/MethodLength:
6
14
  Max: 15
15
+ Rails/Output:
16
+ Enabled: false
@@ -1,6 +1,10 @@
1
1
  # Enables Travis to use their new container-based infrastructure
2
2
  sudo: false
3
3
 
4
+ # Integration tests are using docker-compose
5
+ services:
6
+ - docker
7
+
4
8
  # Build for Ruby
5
9
  language: ruby
6
10
 
@@ -15,35 +19,23 @@ before_install:
15
19
  - gem update bundler
16
20
 
17
21
  # Specify which ruby versions you wish to run your tests on, each version will be used
18
- rvm:
19
- - 2.2.9
20
- - 2.3.6
21
- - 2.4.3
22
- - 2.5.0
23
-
24
- # Define how to run your tests (defaults to `bundle exec rake` or `rake` depending on whether you have a `Gemfile`)
25
- script: "bundle exec rake"
26
-
27
- # Define tasks to be completed before and after tests run . Will allow folding of content on frontend
28
- #before_script:
29
- # - command_1
30
- # - command_2
31
- #
32
- #after_script:
33
- # - command_1
34
- # - command_2
35
-
36
- # Specify the recipients for email notification
37
- #notifications:
38
- # recipients:
39
- # - email-address-1
40
- # - email-address-2
22
+ matrix:
23
+ include:
24
+ - rvm: 2.3.6
25
+ - rvm: 2.5.1
26
+ - env: INTEGRATION_TESTS=true
27
+
28
+ # Define how to run your tests.
29
+ script:
30
+ - |
31
+ # Run either integration tests or specs.
32
+ case "$INTEGRATION_TESTS" in
33
+ true) bin/integration-tests.sh ;;
34
+ *) bundle exec rspec --tag ~integration ;;
35
+ esac
36
+ # Check if conventions are being followed.
37
+ - bundle exec rake rubocop
41
38
 
42
39
  # Disable email notifications
43
- #notifications:
44
- # disabled: true
45
-
46
- # notifications:
47
- # webhooks:
48
- # urls:
49
- # - https://webhooks.gitter.im/e/c6dbb9323007dfcf81df
40
+ notifications:
41
+ disabled: true
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## Version 0.3.0
4
+
5
+ * Asynchronous event listeners (`AsyncEventRouter`).
6
+ * Simplified initialization of event- and command routers.
7
+ * Remove dependency on the `http_event_store` gem.
8
+ * `Event#metadata` is no longer OpenStruct.
9
+
3
10
  ## Version 0.2.0
4
11
 
5
12
  * Synchronous event listeners (see `examples/sinatra/app.rb`).
@@ -0,0 +1,24 @@
1
+ FROM ruby:2.5.1-alpine3.7
2
+ RUN set -eux; \
3
+ apk update; \
4
+ apk add git openssl; \
5
+ apk add build-base libffi-dev
6
+
7
+ ENV DOCKERIZE_VERSION v0.6.1
8
+ RUN wget https://github.com/jwilder/dockerize/releases/download/$DOCKERIZE_VERSION/dockerize-alpine-linux-amd64-$DOCKERIZE_VERSION.tar.gz \
9
+ && tar -C /usr/local/bin -xzvf dockerize-alpine-linux-amd64-$DOCKERIZE_VERSION.tar.gz \
10
+ && rm dockerize-alpine-linux-amd64-$DOCKERIZE_VERSION.tar.gz
11
+
12
+ COPY Gemfile /var/akasha/
13
+ COPY Gemfile.lock /var/akasha/
14
+ COPY akasha.gemspec /var/akasha/
15
+ COPY lib/akasha/version.rb /var/akasha/lib/akasha/version.rb
16
+
17
+ RUN set -eux; \
18
+ cd /var/akasha; \
19
+ bundle
20
+
21
+ COPY . /var/akasha/
22
+ WORKDIR /var/akasha/
23
+
24
+ CMD dockerize -wait http://eventstore:2113 bundle exec rspec --tag integration
data/Gemfile CHANGED
@@ -1,6 +1,6 @@
1
- source "https://rubygems.org"
1
+ source 'https://rubygems.org'
2
2
 
3
- git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
3
+ git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
4
4
 
5
5
  # Gem's dependencies in akasha.gemspec
6
6
  gemspec
@@ -1,35 +1,46 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- akasha (0.2.0)
5
- http_event_store
4
+ akasha (0.3.0)
5
+ corefines (~> 1.11)
6
+ faraday (~> 0.15)
7
+ faraday_middleware
8
+ rack (~> 2.0)
9
+ retries (~> 0.0)
10
+ typhoeus (~> 1.3)
6
11
 
7
12
  GEM
8
13
  remote: https://rubygems.org/
9
14
  specs:
15
+ ast (2.3.0)
10
16
  byebug (10.0.2)
11
17
  coderay (1.1.2)
18
+ corefines (1.11.0)
12
19
  diff-lcs (1.3)
20
+ ethon (0.11.0)
21
+ ffi (>= 1.3.0)
13
22
  faraday (0.15.2)
14
23
  multipart-post (>= 1.2, < 3)
15
24
  faraday_middleware (0.12.2)
16
25
  faraday (>= 0.7.4, < 1.0)
17
- hashie (3.5.7)
18
- http_event_store (0.2.2)
19
- faraday
20
- faraday_middleware
21
- hashie
22
- json
23
- json (2.1.0)
26
+ ffi (1.9.25)
24
27
  method_source (0.9.0)
25
28
  multipart-post (2.0.0)
29
+ parallel (1.12.0)
30
+ parser (2.4.0.0)
31
+ ast (~> 2.2)
32
+ powerpack (0.1.1)
26
33
  pry (0.11.3)
27
34
  coderay (~> 1.1.0)
28
35
  method_source (~> 0.9.0)
29
36
  pry-byebug (3.6.0)
30
37
  byebug (~> 10.0)
31
38
  pry (~> 0.10)
39
+ rack (2.0.5)
40
+ rainbow (2.2.2)
41
+ rake
32
42
  rake (10.5.0)
43
+ retries (0.0.5)
33
44
  rspec (3.7.0)
34
45
  rspec-core (~> 3.7.0)
35
46
  rspec-expectations (~> 3.7.0)
@@ -43,7 +54,20 @@ GEM
43
54
  diff-lcs (>= 1.2.0, < 2.0)
44
55
  rspec-support (~> 3.7.0)
45
56
  rspec-support (3.7.1)
57
+ rspec-wait (0.0.9)
58
+ rspec (>= 3, < 4)
59
+ rubocop (0.50.0)
60
+ parallel (~> 1.10)
61
+ parser (>= 2.3.3.1, < 3.0)
62
+ powerpack (~> 0.1)
63
+ rainbow (>= 2.2.2, < 3.0)
64
+ ruby-progressbar (~> 1.7)
65
+ unicode-display_width (~> 1.0, >= 1.0.1)
66
+ ruby-progressbar (1.9.0)
46
67
  timecop (0.9.1)
68
+ typhoeus (1.3.0)
69
+ ethon (>= 0.9.0)
70
+ unicode-display_width (1.3.0)
47
71
 
48
72
  PLATFORMS
49
73
  ruby
@@ -54,7 +78,9 @@ DEPENDENCIES
54
78
  pry-byebug
55
79
  rake (~> 10.0)
56
80
  rspec (~> 3.7)
57
- timecop
81
+ rspec-wait (~> 0.0.9)
82
+ rubocop (~> 0.50)
83
+ timecop (~> 0.9)
58
84
 
59
85
  BUNDLED WITH
60
86
  1.16.2
data/README.md CHANGED
@@ -20,74 +20,81 @@ Or install it yourself as:
20
20
 
21
21
  ## Usage
22
22
 
23
- The code below uses Sinatra to demonstrate how to use the library in a web application.
24
- This library makes no assumptions about any web framework, you can use it in any way you see fit.
23
+ There is an example Sinatra app under `examples/sinatra` showing how to use the library in a web application.
24
+ This library itself makes no assumptions about any web framework, you can use it in any way you see fit.
25
25
 
26
- ```ruby
27
- require 'akasha'
28
- require 'sinatra'
29
-
30
- class User < Akasha::Aggregate
31
- def sign_up(email:, password:, admin: false, **)
32
- changeset.append(:user_signed_up, email: email, password: password, admin: admin)
33
- end
34
-
35
- def on_user_signed_up(email:, password:, admin:, **)
36
- @email = email
37
- @password = password
38
- @admin = admin
39
- end
40
- end
41
-
42
-
43
- before do
44
- @router = Akasha::CommandRouter.new
45
-
46
- # Aggregates will load from and save to in-memory storage.
47
- repository = Akasha::Repository.new(Akasha::Storage::MemoryEventStore.new)
48
- Akasha::Aggregate.connect!(repository)
49
-
50
- # This is how you link commands to aggregates.
51
- @router.register_default_route(:sign_up, User)
52
-
53
- # Nearly identital to the default handling above but we're setting the admin
54
- # flag to demo custom command handling.
55
- @router.register_route(:sign_up_admin) do |aggregate_id, **data|
56
- user = User.find_or_create(aggregate_id)
57
- user.sign_up(email: data[:email], password: data[:password], admin: true)
58
- user.save!
59
- end
60
- end
61
-
62
- post '/users/:user_id' do # With CQRS client pass unique aggregate ids.
63
- @router.route!(:sign_up,
64
- params[:user_id],
65
- email: params[:email],
66
- password: params[:password])
67
- 'OK'
68
- end
69
- ```
70
-
71
- > Currently, only memory-based repository is supported.
72
-
73
- ## Next steps
26
+ ## TODO
74
27
 
75
28
  - [x] Command routing (default and user-defined)
76
29
  - [x] Synchronous EventHandler
77
30
  - [x] HTTP Eventstore storage backend
78
- - [ ] Telemetry (Dogstatsd)
79
- - [ ] Event#id for better idempotence (validate this claim)
80
- - [ ] Namespacing for events and aggregates
31
+ - [x] Event#id for better idempotence (validate this claim)
32
+ - [x] Async EventHandlers (storing cursors in Eventstore, configurable durability guarantees)
33
+ - [x] Uniform intetrface for Client -- use Event.
34
+ - [x] Rewrite Client
35
+ - [x] Refactor Client code
36
+ - [x] Take care of created_at/updated_at (saved_at?)
37
+ - [x] Tests for HttpEventStore
38
+ - [x] Projections
39
+ - [x] Test for AsyncEventRouter using events not aggregate
40
+ - [x] BUG: Projection reorders events
41
+ - [x] Simplify AsyncEventRouter init
42
+ - [x] SyncEventRouter => EventRouter
43
+ - [x] Metadata not persisted
44
+ - [x] Refactoring & simplification.
45
+ - [x] Hash-based event and command router
46
+ - [x] Do we need EventListener class? Yes.
47
+ - [x] Assymetry between data and metadata.
48
+ - [x] Faster shutdown.
49
+ - [ ] Namespacing for events and aggregates and the projection
81
50
  - [ ] Version-based concurrency
82
- - [ ] Async EventHandlers (storing cursors in Eventstore, configurable durability guarantees)
51
+ - [ ] Telemetry (Dogstatsd)
83
52
  - [ ] Socket-based Eventstore storage backend
84
53
 
54
+
85
55
  ## Development
86
56
 
87
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
57
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. See Running tests.
58
+
59
+ You can also run `bin/console` for an interactive prompt that will allow you to experiment.
88
60
 
89
61
  To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
90
62
 
63
+
64
+ ## Running tests
65
+
66
+ Some tests require Eventstore to be running and available via `eventstore` host name. You can exclude these specs:
67
+
68
+ ```
69
+ rspec --tag ~integration
70
+ ```
71
+
72
+ The easiest way to run integration tests:
73
+
74
+ ```
75
+ /bin/integration-tests.sh
76
+ ```
77
+
78
+ This will use docker-compose to spin up containers containing the dependencies and tests themselves.
79
+
80
+ Because it's pretty slow, you may want to spin up a docker container containing event store:
81
+
82
+ ```
83
+ docker run -e EVENTSTORE_START_STANDARD_PROJECTIONS=true --name akasha-eventstore -it -p 2113:2113 -p 1113:1113 -d eventstore/eventstore
84
+ ```
85
+
86
+ and use RSpec run just integration specs like so:
87
+
88
+ ```
89
+ rspec --tag integration
90
+ ```
91
+
92
+ or run all tests:
93
+
94
+ ```
95
+ rspec
96
+ ```
97
+
91
98
  ## Contributing
92
99
 
93
100
  Bug reports and pull requests are welcome on GitHub at https://github.com/bilus/akasha.
data/Rakefile CHANGED
@@ -1,6 +1,11 @@
1
- require "bundler/gem_tasks"
2
- require "rspec/core/rake_task"
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+ require 'rubocop/rake_task'
4
+
5
+ RuboCop::RakeTask.new(:rubocop) do |task|
6
+ task.options = ['--rails', '--display-cop-names']
7
+ end
3
8
 
4
9
  RSpec::Core::RakeTask.new(:spec)
5
10
 
6
- task :default => :spec
11
+ task default: :spec
@@ -9,9 +9,9 @@ Gem::Specification.new do |spec|
9
9
  spec.authors = ['Marcin Bilski']
10
10
  spec.email = ['marcin@tooploox.com']
11
11
 
12
- spec.summary = %q{CQRS library for Ruby}
13
- spec.description = %q{A simple CQRS library for Ruby.}
14
- spec.homepage = "https://github.com/bilus/akasha"
12
+ spec.summary = 'CQRS library for Ruby'
13
+ spec.description = 'A simple CQRS library for Ruby.'
14
+ spec.homepage = 'https://github.com/bilus/akasha'
15
15
  spec.license = 'MIT'
16
16
 
17
17
  # Specify which files should be added to the gem when it is released.
@@ -23,11 +23,18 @@ Gem::Specification.new do |spec|
23
23
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
24
24
  spec.require_paths = ['lib']
25
25
 
26
- spec.add_dependency 'http_event_store'
26
+ spec.add_dependency 'faraday', '~> 0.15'
27
+ spec.add_dependency 'faraday_middleware'
28
+ spec.add_dependency 'typhoeus', '~> 1.3'
29
+ spec.add_dependency 'rack', '~> 2.0'
30
+ spec.add_dependency 'retries', '~> 0.0'
31
+ spec.add_dependency 'corefines', '~>1.11'
27
32
 
28
33
  spec.add_development_dependency 'bundler', '~> 1.16'
34
+ spec.add_development_dependency 'pry-byebug'
29
35
  spec.add_development_dependency 'rake', '~> 10.0'
30
36
  spec.add_development_dependency 'rspec', '~> 3.7'
31
- spec.add_development_dependency 'timecop'
32
- spec.add_development_dependency 'pry-byebug'
37
+ spec.add_development_dependency 'rspec-wait', '~> 0.0.9'
38
+ spec.add_development_dependency 'rubocop', '~> 0.50'
39
+ spec.add_development_dependency 'timecop', '~> 0.9'
33
40
  end
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require "bundler/setup"
4
- require "akasha"
3
+ require 'bundler/setup'
4
+ require 'akasha'
5
5
 
6
6
  # You can add fixtures and/or initialization code here to make experimenting
7
7
  # with your gem easier. You can also use a different console, if you like.
@@ -10,5 +10,5 @@ require "akasha"
10
10
  # require "pry"
11
11
  # Pry.start
12
12
 
13
- require "irb"
13
+ require 'irb'
14
14
  IRB.start(__FILE__)
@@ -0,0 +1,40 @@
1
+ #!/usr/bin/env bash
2
+
3
+ # define some colors to use for output
4
+ RED='\033[0;31m'
5
+ GREEN='\033[0;32m'
6
+ NC='\033[0m'
7
+
8
+ PROJECT=ci
9
+
10
+ # kill and remove any running containers
11
+ cleanup () {
12
+ docker-compose -p $PROJECT down
13
+ }
14
+ # catch unexpected failures, do cleanup and output an error message
15
+ trap 'cleanup ; printf "${RED}Tests Failed For Unexpected Reasons${NC}\n"'\
16
+ HUP INT QUIT PIPE TERM
17
+ cd docker
18
+ echo "Starting tests"
19
+ # build and run the composed services
20
+ docker-compose -p $PROJECT up -d --build
21
+ if [ $? -ne 0 ] ; then
22
+ printf "${RED}Docker Compose Failed${NC}\n"
23
+ exit -1
24
+ fi
25
+ echo "Waiting for tests to finish"
26
+ # wait for the test service to complete and grab the exit code
27
+ TEST_EXIT_CODE=`docker wait ${PROJECT}_tests_1`
28
+ echo "Listing docker logs"
29
+ # output the logs for the test (for clarity)
30
+ docker logs ${PROJECT}_tests_1
31
+ # inspect the output of the test and display respective message
32
+ if [ -z ${TEST_EXIT_CODE+x} ] || [ "$TEST_EXIT_CODE" -ne 0 ] ; then
33
+ printf "${RED}Tests Failed${NC} - Exit Code: $TEST_EXIT_CODE\n"
34
+ else
35
+ printf "${GREEN}Tests Passed${NC}\n"
36
+ fi
37
+ # call the cleanup fuction
38
+ cleanup
39
+ # exit the script with the same code as the test service code
40
+ exit $TEST_EXIT_CODE