dry-facts 0.1.0 → 0.2.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: 716f50956a3fbb10524b482e39e76df2daaad30ad67261cdb817d7376f1cb4d8
4
- data.tar.gz: deb420fac8620518e6b6ad44d57d5604c72652a9c762aee09c6c36afac104b79
3
+ metadata.gz: 2e4989c09bf4471795f9770ae4c20bd9703198f557f1df1ec75e21bbbc390e51
4
+ data.tar.gz: 52fa236f7c4dca8c782e3671e0509ebb0e7965cd94453e4a16600cd814660f20
5
5
  SHA512:
6
- metadata.gz: 3d7c5dfa75ff3ff0268aae2b98334331c5863d32b7c8e5a45b95853ade084c1dbb13e7b45421f6661cd8501411add01f8af3c6c3f9510018467592f66ad1a3ad
7
- data.tar.gz: e5856d530722f40c4f5f175b163f225ce3848cb7de923d3a4f63a1b47aa6d9d02406b9462a0bac25ba41980b55932a422bc22e0f80dfecc8a35ba024abc413f3
6
+ metadata.gz: 44864e6199ee8c8d983af7c0c6335f66dec1d55f373d30d265fee97ca88aa541c0f2fa12baa52ee9b67a6543dde8d27ddf06453498da16f6649db17e6ece9e5d
7
+ data.tar.gz: fac80ac86674542a77946912b8d58b0f0176c033958e694ab334a99f9daece138b5ccd1012cfbebbae6a0224f4ed54af7fa4f9b8e7d6d8a382624f9c5c48bf7c
data/README.md CHANGED
@@ -1,8 +1,7 @@
1
1
  # Dry::Facts
2
2
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/dry/facts`. To experiment with that code, run `bin/console` for an interactive prompt.
4
-
5
- TODO: Delete this and the text above, and describe your gem
3
+ EventSourcing ruby toolkit, somewhat based on dry-rb primitives.
4
+ Opinionated. Raw.
6
5
 
7
6
  ## Installation
8
7
 
@@ -32,7 +31,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
32
31
 
33
32
  ## Contributing
34
33
 
35
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/dry-facts.
34
+ Bug reports and pull requests are welcome on GitHub at https://github.com/andriytyurnikov/dry-facts.
36
35
 
37
36
  ## License
38
37
 
data/ROADMAP.md CHANGED
@@ -25,7 +25,10 @@ Aggregates, generate and persist events. Events persisted in EventStore.
25
25
 
26
26
  ## Approach
27
27
 
28
- Type system will be used to allow generation of GraphQL from core types
28
+ Minimal prototypes of primitives
29
+ Minimal prototype of integrated system
30
+ Minimal prototype of application based on system
31
+ Refactoring
29
32
 
30
33
  ## Challenges
31
34
 
@@ -43,16 +46,16 @@ Implements the Unit-Of-Work and Identity-Map patterns to ensure each aggregate i
43
46
  No explicit types ?
44
47
 
45
48
 
46
- ## Step by step
49
+ ## Checklist
47
50
  * Command
48
51
  - [x] Skeleton without any meaningful structure
49
52
  - [x] With inner class input contract
50
53
  - [x] With inner class output contract
51
54
  - [x] With explicit method input contract
52
55
  - [x] With explicit method output contract
53
- - [ ] Without input contract
54
- - [ ] Without output contract
55
- - [ ] Unified result
56
+ - [x] Without input contract
57
+ - [x] Without output contract
58
+ - [ ] Unified result (Relay?)
56
59
  - [ ] Multistep
57
60
  - [ ] Composition
58
61
  - [ ] Transactions
@@ -60,34 +63,47 @@ No explicit types ?
60
63
  - [ ] Validation with contract
61
64
  - [ ] Validation with multiple steps
62
65
  - [ ] Validation with custom behavior in the arbitrary point of command
66
+ - [ ] Docs from comments
63
67
  - [ ] Code & test generator
64
68
  * EventStore
65
- - [ ] In memory
69
+ - [x] In memory store
66
70
  - [ ] Serialization and typecasting?
67
- - [ ] Transactions, causality, correlations
71
+ - [x] Aggregates
72
+ - [ ] Causality
73
+ - [ ] Correlations
74
+ - [ ] Transactions
68
75
  - [ ] Lifecycle and maintenance tasks (snapshots (rolling, deployment) and versioning)
69
- - [ ] Sequel
70
- - [ ] ActiveRecord
71
- - [ ] Kafka
76
+ - [ ] Sequel store
77
+ - [ ] ActiveRecord store
78
+ - [ ] Redis store
79
+ - [ ] Kafka store
72
80
  - [ ] Docs from comments
73
81
  * Event
74
- - [ ] Hash
75
- - [ ] Object?
82
+ - [ ] Hash?
83
+ - [x] Object?
84
+ - [ ] Aggregate DSL
85
+ - [ ] Correlation DSL
86
+ - [ ] Causation DSL
87
+ - [ ] Module?
76
88
  - [ ] With schema?
77
89
  - [ ] Naming and code evolution?
78
90
  - [ ] Code & test generator
79
91
  - [ ] Docs from comments
80
92
  * Aggregates
81
- - [ ] Skeleton without any functionality
82
- - [ ] Class instance
93
+ - [x] Skeleton without any functionality
94
+ - [x] Class instance
95
+ - [x] With events
96
+ - [x] Data transfer DSL
83
97
  - [ ] Hash instance
84
- - [ ] With contract
85
- - [ ] With events
98
+ - [ ] With contract?
86
99
  - [ ] Code & test generator
87
100
  - [ ] Docs from comments
88
101
  * GraphQL generation
89
102
  - [x] Skeleton without generation
90
- - [x] From hash
103
+ - [ ] Type generation
104
+ - [ ] Mutation generation
105
+ - [ ] Query generation
106
+ - [ ] From hash
91
107
  - [ ] Naive generation
92
108
  - [ ] Customizable & helpers
93
109
  * CI
@@ -12,6 +12,17 @@ module Dry
12
12
  attr_reader :uuid
13
13
 
14
14
  class << self
15
+ def build_one_from_events events
16
+ self
17
+ .new(events)
18
+ end
19
+
20
+ def build_all_from_events events
21
+ events
22
+ .group_by {|e| e.aggregate_id }
23
+ .map {|_, g_events| build_one_from_events(g_events) }
24
+ end
25
+
15
26
  def event_handlers
16
27
  @event_handlers
17
28
  end
@@ -25,7 +36,7 @@ module Dry
25
36
  @event_handlers[name] = method_name
26
37
  end
27
38
 
28
- def aggregate_data_from_events(*event_klasses)
39
+ def aggregate_data_from_event_types(*event_klasses)
29
40
  event_klasses.each do |klass|
30
41
  define_event_handler klass.name, :_transfer_data_from_event
31
42
  end
@@ -35,12 +46,10 @@ module Dry
35
46
 
36
47
  def initialize(events)
37
48
  @events = events || []
38
- #TODO ensure same aggregate_id
49
+ @uuid = @id = if @events.first
50
+ @events.first.aggregate_id
51
+ end
39
52
  @events.each {|e| self.send :_handle_event, e}
40
- @uuid = @id = @events.first.aggregate_id
41
- end
42
-
43
- def no_op
44
53
  end
45
54
 
46
55
  private
@@ -53,13 +62,10 @@ module Dry
53
62
  version: '0' } }
54
63
  end
55
64
 
56
- def _inject_aggregate_metadata_into_event event
57
- event.metadata[:aggregate] =
58
- _default_aggregate_metadata
59
- .merge(event.metadata[:aggregate] || {})
60
- end
61
-
62
65
  def _handle_event event
66
+ if self.uuid != event.metadata[:aggregate_id]
67
+ fail "This event is not mine!"
68
+ end
63
69
  handler_name =
64
70
  self
65
71
  .class
@@ -11,7 +11,7 @@ module Dry
11
11
 
12
12
  class << self
13
13
  def input_contract
14
- @input_contract
14
+ @input_contract if defined?(@input_contract)
15
15
  end
16
16
 
17
17
  def input_contract= value
@@ -19,7 +19,7 @@ module Dry
19
19
  end
20
20
 
21
21
  def output_contract
22
- @output_contract
22
+ @output_contract if defined?(@output_contract)
23
23
  end
24
24
 
25
25
  def output_contract= value
@@ -54,7 +54,7 @@ module Dry
54
54
  self::InputContract
55
55
  else
56
56
  self.input_contract
57
- end.new(**input)
57
+ end.yield_self {|c| _enforce_contract_if_present(c, input) }
58
58
  end
59
59
 
60
60
  def _enforce_output_contract_on output
@@ -62,13 +62,21 @@ module Dry
62
62
  self::OutputContract
63
63
  else
64
64
  self.output_contract
65
- end.new(**output)
65
+ end.yield_self {|c| _enforce_contract_if_present(c, output) }
66
66
  end
67
67
 
68
68
  def _execute_with input
69
69
  self.new.call input
70
70
  end
71
71
 
72
+ def _enforce_contract_if_present(contract, data)
73
+ if contract
74
+ contract.new(**data)
75
+ else
76
+ data
77
+ end
78
+ end
79
+
72
80
  end
73
81
 
74
82
  end
@@ -18,7 +18,8 @@ module Dry
18
18
  def from_h(h)
19
19
  Object
20
20
  .const_get(h[:metadata][:type][:name])
21
- .new(metadata: h[:metadata], data: h[:data])
21
+ .new( data: h[:data],
22
+ metadata: h[:metadata])
22
23
  end
23
24
  end
24
25
  # object/hash
@@ -37,6 +38,7 @@ module Dry
37
38
  metadata: {}
38
39
  @metadata = _default_metadata_merged_with(metadata) || Hash.new
39
40
  @data = {}.merge(data) || Hash.new
41
+ freeze
40
42
  end
41
43
 
42
44
  def id
@@ -69,11 +71,10 @@ module Dry
69
71
  generated_default_uuid = SecureRandom.uuid
70
72
  generated_default_id = generated_default_uuid
71
73
 
72
- { id: (generated_default_id),
73
- uuid: (generated_default_uuid),
74
+ { id: (generated_default_id),
75
+ uuid: (generated_default_uuid),
74
76
  aggregate_id: generated_default_aggregate_id,
75
- type: { name: self.class.name,
76
- version: 0 } }
77
+ type: { name: self.class.name } }
77
78
  .merge(metadata || {})
78
79
  end
79
80
 
@@ -9,15 +9,16 @@ module Dry
9
9
 
10
10
  def aggregate_from_event(klass, event)
11
11
  get_events_by_key(
12
- key: :aggregate_id,
13
- value: event.to_h[:data][:aggregate_id])
12
+ key: :aggregate_id,
13
+ value: event.to_h[:data][:aggregate_id])
14
14
  .yield_self {|events| klass.new(events)}
15
15
  end
16
16
 
17
- # persist_event(event)
18
- def persist_event(event)
17
+ # persist_event_and_return(event)
18
+ def persist_event_and_return(event)
19
19
  # validate & fail
20
20
  @serialized_events << event.to_h
21
+ event
21
22
  end
22
23
 
23
24
  # get_event_by_id(42)
@@ -41,11 +42,14 @@ module Dry
41
42
  end
42
43
 
43
44
  def serialize_event(fact)
44
- fact.to_h
45
+ fact
46
+ .to_h
45
47
  end
46
48
 
47
49
  def deserialize_event(serialized_event)
48
- Event.from_h(serialized_event)
50
+ Event
51
+ .from_h(serialized_event)
52
+ .freeze
49
53
  end
50
54
 
51
55
  end
@@ -1,5 +1,5 @@
1
1
  module Dry
2
2
  module Facts
3
- VERSION = "0.1.0"
3
+ VERSION = "0.2.0"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dry-facts
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andriy Tyurnikov
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-02-19 00:00:00.000000000 Z
11
+ date: 2018-02-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: require_all
@@ -174,7 +174,6 @@ files:
174
174
  - lib/dry/facts/event.rb
175
175
  - lib/dry/facts/event_store.rb
176
176
  - lib/dry/facts/version.rb
177
- - lib/dry/facts/workflow.rb
178
177
  homepage: https://github.com/andriytyurnikov/dry-facts
179
178
  licenses:
180
179
  - MIT
@@ -1,9 +0,0 @@
1
- module Dry
2
- module Facts
3
- class Workflow
4
-
5
-
6
-
7
- end
8
- end
9
- end