conflow 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
  SHA256:
3
- metadata.gz: b85fd52b7c1a2161135fc389c45b3f1e6754462a17ef30463435f1c919685950
4
- data.tar.gz: a5f05aa2c69b8426a72dc1070834ec74120a5053a74f93250098765c461105ef
3
+ metadata.gz: 572a2e10d542d2914de25fc748c1c153938e59b081aaef7829208395a86e462b
4
+ data.tar.gz: 99a32aa33c314eeabfa4feed3b386072ba2146139b552b257c59cd4b693fcca0
5
5
  SHA512:
6
- metadata.gz: 3291b765c557576651568d735b3bad21e7a191919a858e9365bbf7da97d632d09f99f3c7a2f35d3133b03d3e82a9802489dd1b63542bd1343325f89c74c22845
7
- data.tar.gz: a6797479cf68b310791680b2709ed54ebb9e372e26e87a1ffb2e685418a33eefa1b621bf5f68aa6ec05024c54d58f427123335ba204049a3fd7bfba4aa6d026e
6
+ metadata.gz: 8538390ead7bcc20bcea935aee1ec4d4ec7359eba95a89a8a5ddd14a3fbec25b69f9900d4548a4fd6370ae94eff13471ac794fe39a593d64a16ae0f2bf0abdf3
7
+ data.tar.gz: 53f5221e6bb9c0bd7dffdfdae3f0cb955f170e3aaa22a281a0e7f682952d9ad946de7daa93b0899935a5e77864f8178e5219e766182f74cbddfc16ea0d12881a
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- conflow (0.2.0)
4
+ conflow (0.3.0)
5
5
  redis (~> 4.0)
6
6
 
7
7
  GEM
@@ -11,11 +11,11 @@ GEM
11
11
  coderay (1.1.2)
12
12
  connection_pool (2.2.1)
13
13
  diff-lcs (1.3)
14
- docile (1.1.5)
14
+ docile (1.3.0)
15
15
  json (2.1.0)
16
16
  method_source (0.9.0)
17
17
  parallel (1.12.1)
18
- parser (2.5.0.3)
18
+ parser (2.5.0.4)
19
19
  ast (~> 2.4.0)
20
20
  powerpack (0.1.1)
21
21
  pry (0.11.3)
@@ -45,8 +45,8 @@ GEM
45
45
  ruby-progressbar (~> 1.7)
46
46
  unicode-display_width (~> 1.0, >= 1.0.1)
47
47
  ruby-progressbar (1.9.0)
48
- simplecov (0.15.1)
49
- docile (~> 1.1.0)
48
+ simplecov (0.16.0)
49
+ docile (~> 1.1)
50
50
  json (>= 1.8, < 3)
51
51
  simplecov-html (~> 0.10.0)
52
52
  simplecov-html (0.10.2)
data/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # Conflow
2
2
 
3
- [![Build Status](https://travis-ci.org/fanfilmu/conflow.svg?branch=master)](https://travis-ci.org/fanfilmu/conflow) [![Maintainability](https://api.codeclimate.com/v1/badges/80b66a285ca1803f391a/maintainability)](https://codeclimate.com/github/fanfilmu/conflow/maintainability) [![Test Coverage](https://api.codeclimate.com/v1/badges/80b66a285ca1803f391a/test_coverage)](https://codeclimate.com/github/fanfilmu/conflow/test_coverage)
3
+ [![Gem Version](https://badge.fury.io/rb/conflow.svg)](https://badge.fury.io/rb/conflow) [![Build Status](https://travis-ci.org/fanfilmu/conflow.svg?branch=master)](https://travis-ci.org/fanfilmu/conflow) [![Maintainability](https://api.codeclimate.com/v1/badges/80b66a285ca1803f391a/maintainability)](https://codeclimate.com/github/fanfilmu/conflow/maintainability) [![Test Coverage](https://api.codeclimate.com/v1/badges/80b66a285ca1803f391a/test_coverage)](https://codeclimate.com/github/fanfilmu/conflow/test_coverage)
4
4
 
5
- Conflow allows defining comlicated workflows with dependencies. Inspired by [Gush](https://github.com/chaps-io/gush) (the idea) and [Redis::Objects](https://github.com/nateware/redis-objects) (the implementation) it focuses solely on dependency logic, while leaving queueing jobs and executing them entirely in hands of the programmer.
5
+ Conflow allows defining complicated workflows with dependencies. Inspired by [Gush](https://github.com/chaps-io/gush) (the idea) and [Redis::Objects](https://github.com/nateware/redis-objects) (the implementation) it focuses solely on dependency logic, while leaving queueing jobs and executing them entirely in hands of the programmer.
6
6
 
7
7
  Please have a look at `Gush` if you already use Rails and ActiveJob - it might suit your needs better.
8
8
 
@@ -97,6 +97,24 @@ end
97
97
 
98
98
  ![Created graph](https://camo.githubusercontent.com/0b1ee59994323900906264ea50fbc9169e4d21dd/68747470733a2f2f63686172742e676f6f676c65617069732e636f6d2f63686172743f63686c3d646967726170682b472b2537422530442530412b2b72616e6b6469722533444c522533422530442530412b2b25323253544152542532322b2d2533452b25323246697273744a6f622532322530442530412b2b25323253544152542532322b2d2533452b253232496e646570656e64656e744a6f622532322530442530412b2b25323246697273744a6f622532322b2d2533452b2532325365636f6e644a6f622532322530442530412b2b253232496e646570656e64656e744a6f622532322b2d2533452b2532325365636f6e644a6f622532322530442530412b2b2532325365636f6e644a6f622532322b2d2533452b25323246696e69736855702532322530442530412b2b25323246696e69736855702532322b2d2533452b253232454e442532322530442530412537442530442530412b266368743d6776)
99
99
 
100
+ ### Hooks
101
+
102
+ If you want to modify your flow dynamically depending on results of your jobs, you can use hooks.
103
+
104
+ Hooks are methods defined on the `Flow` objects which will be called with result of the job (value returned by `Worker`, see [Performing jobs](https://github.com/fanfilmu/conflow#performing-jobs)).
105
+
106
+ ```ruby
107
+ class MyFlow < ApplicationFlow
108
+ def configure
109
+ run CollectEmails, hook: :send_notifications
110
+ end
111
+
112
+ def send_notifications(emails)
113
+ emails.each { |email| run SendNotification, params: { email: email } }
114
+ end
115
+ end
116
+ ```
117
+
100
118
  ### Performing jobs
101
119
 
102
120
  To perform job, use `Conflow::Worker` mixin. It adds `#perform` method, which accepts two arguments: IDs of the flow and the job.
@@ -127,6 +145,24 @@ SecondJob.new({}).call
127
145
  FinishUp.new({}).call
128
146
  ```
129
147
 
148
+ ## Theory
149
+
150
+ The main idea of the gem is, obviously, a directed graph containing information about dependencies. It is stored in Redis in following fields:
151
+
152
+ * `conflow:job:<id>:successors` - ([List](https://redis.io/topics/data-types#lists)) containing IDs of jobs which depend on `<id>`
153
+ * `conflow:flow:<id>:indegee` - ([Sorted Set](https://redis.io/topics/data-types#sorted-sets)) set of all unqueued jobs with score representing how many dependencies are not yet fulfilled
154
+
155
+ There are three main actions that can be performed on this graph (Redis-wise):
156
+
157
+ 1. Queue jobs
158
+ Removes all jobs with score 0 from `:indegree` set
159
+ 2. Complete job
160
+ Decrement scores of all of the job's successors by one
161
+ 3. Add job
162
+ Add job ID to `:successors` list for all jobs on which it depends and add job itself to `:indegree` set
163
+
164
+ All of these actions are performed via `eval`/`evalsha` - it lifts problems with synchronization (as scripts are executed as if in transaction) and significantly reduces amount of requests made to Redis.
165
+
130
166
  ## Development
131
167
 
132
168
  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.
data/lib/conflow.rb CHANGED
@@ -6,6 +6,7 @@ require "digest"
6
6
  require "json"
7
7
  require "redis"
8
8
 
9
+ require "conflow/redis"
9
10
  require "conflow/redis/connection_wrapper"
10
11
  require "conflow/redis/field"
11
12
  require "conflow/redis/value_field"
@@ -34,6 +35,12 @@ require "conflow/worker"
34
35
  # while leaving queueing jobs and executing them entirely in hands of the programmer.
35
36
  module Conflow
36
37
  class << self
38
+ # Assigns Redis connection to be used by {Conflow}. It will be wrapped in ConnectionWrapper
39
+ # for Redis instances, in order to have single API containing #with method.
40
+ # You can also assign ConnectionPool instance.
41
+ # @param conn [Redis, ConnectionPool] Redis connection
42
+ # @example
43
+ # Conflow.redis = Redis.new
37
44
  def redis=(conn)
38
45
  @redis =
39
46
  if defined?(ConnectionPool) && conn.is_a?(ConnectionPool)
@@ -43,6 +50,7 @@ module Conflow
43
50
  end
44
51
  end
45
52
 
53
+ # @return [Conflow::Redis::ConnectionWrapper, ConnectionPool] Wrapped Redis connection
46
54
  def redis
47
55
  self.redis = ::Redis.current unless defined?(@redis)
48
56
  @redis
@@ -15,13 +15,16 @@ module Conflow
15
15
  def run(job_class, params: {}, after: [], hook: nil)
16
16
  build_job(job_class, params, hook).tap do |job|
17
17
  job_classes[job_class] = job
18
- after = prepare_dependencies(after)
18
+ after = prepare_dependencies(after).compact
19
19
 
20
20
  call_script(Conflow::Redis::AddJobScript, job, after: after)
21
21
  queue_available_jobs
22
22
  end
23
23
  end
24
24
 
25
+ # Finishes job, changes its status, runs hook if it's present and queues new available jobs
26
+ # @param job [Conflow::Job] job to be marked as finished
27
+ # @param result [Object] result of the job to be passed to hook
25
28
  def finish(job, result = nil)
26
29
  send(job.hook.to_s, result) unless job.hook.nil?
27
30
  call_script(Conflow::Redis::CompleteJobScript, job)
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Conflow
4
+ # Redis module contains all logic related to handling flows in Redis
5
+ # @api private
6
+ module Redis
7
+ end
8
+ end
@@ -3,6 +3,7 @@
3
3
  module Conflow
4
4
  module Redis
5
5
  # Adds new job to flow
6
+ # @api private
6
7
  class AddJobScript < Script
7
8
  # script accepts keys: flow.job_ids, flow.indegree, and keys successors of the jobs on which new job depends.
8
9
  # It also accepts one argument: id of the new job
@@ -3,55 +3,28 @@
3
3
  module Conflow
4
4
  module Redis
5
5
  # Represents Redis list. It's methods mirror most used Array methods.
6
+ # @api private
6
7
  class ArrayField < Field
7
8
  include Enumerable
8
9
 
9
- def [](index)
10
- command :lindex, [key, index]
11
- end
12
-
13
- def []=(index, value)
14
- command :lset, [key, index, value]
15
- end
16
-
17
- def insert(value, after: nil, before: nil)
18
- if after
19
- command :linsert, [key, :after, after, value]
20
- elsif before
21
- command :linsert, [key, :before, before, value]
22
- else
23
- raise ArgumentError, "You need to pass one of [:after, :before] keywords"
24
- end
25
- end
26
-
10
+ # @return [Integer] number of elements in list
27
11
  def size
28
12
  command :llen, [key]
29
13
  end
30
14
 
15
+ # @return [Array] Ruby Array representation of Redis list
31
16
  def to_a
32
17
  command :lrange, [key, 0, -1]
33
18
  end; alias to_ary to_a
34
19
 
35
- def pop
36
- command :rpop, [key]
37
- end
38
-
20
+ # @param values [String...] one or more values to be added to the list
21
+ # @return [String] Redis response
39
22
  def push(*values)
40
23
  command :rpush, [key, values]
41
24
  end; alias << push
42
25
 
43
- def concat(ary)
44
- push(*ary)
45
- end
46
-
47
- def shift
48
- command :lpop, [key]
49
- end
50
-
51
- def unshift(value)
52
- command :lpush, [key, value]
53
- end
54
-
26
+ # Replace contents of Redis list
27
+ # @param new_array [Array] array of new values
55
28
  def overwrite(new_array)
56
29
  redis.with do |conn|
57
30
  conn.pipelined do
@@ -61,10 +34,14 @@ module Conflow
61
34
  end
62
35
  end
63
36
 
37
+ # Iterates over list
38
+ # @see to_a
64
39
  def each(&block)
65
40
  to_a.each(&block)
66
41
  end
67
42
 
43
+ # @param other [Object] Object to compare value with. Handles Arrays and other {ArrayField} objects
44
+ # @return [Boolean] true if equal
68
45
  def ==(other)
69
46
  case other
70
47
  when Array then to_a == other
@@ -73,6 +50,8 @@ module Conflow
73
50
  end
74
51
  end
75
52
 
53
+ # String representation of the list
54
+ # @see to_a
76
55
  def to_s
77
56
  to_a.to_s
78
57
  end
@@ -3,6 +3,7 @@
3
3
  module Conflow
4
4
  module Redis
5
5
  # Adds new job to flow
6
+ # @api private
6
7
  class CompleteJobScript < Script
7
8
  self.script = <<~LUA
8
9
  local indegree_set = KEYS[1]
@@ -3,6 +3,7 @@
3
3
  module Conflow
4
4
  module Redis
5
5
  # Wraps Redis connection to behave like connection pool
6
+ # @api private
6
7
  class ConnectionWrapper
7
8
  # @param redis [Redis] Redis connection to be wrapped
8
9
  def initialize(redis)
@@ -3,10 +3,13 @@
3
3
  module Conflow
4
4
  module Redis
5
5
  # Base class for fields. All fields are assigned a Redis key.
6
+ # @api private
6
7
  class Field
8
+ # Redis key
7
9
  attr_reader :key
8
10
  alias id key
9
11
 
12
+ # @param key [String] Redis key to store the field in
10
13
  def initialize(key)
11
14
  @key = key
12
15
  end
@@ -3,9 +3,11 @@
3
3
  module Conflow
4
4
  module Redis
5
5
  # Helper class for defining getter and setter methods for Fields
6
+ # @api private
6
7
  class FieldBuilder
7
8
  # This dynamic module contains accessor methods for a field
8
9
  class FieldAccessor < Module
10
+ # Creates new dynamic module with accessor methods for a field
9
11
  def initialize(field_name, klass, methods)
10
12
  super() do
11
13
  define_getter(field_name, klass) if methods.include?(:getter)
@@ -13,6 +15,7 @@ module Conflow
13
15
  end
14
16
  end
15
17
 
18
+ # Defines getter method, which will return proper {Conflow::Redis::Field}
16
19
  def define_getter(field_name, klass)
17
20
  instance_var = "@#{field_name}"
18
21
 
@@ -22,6 +25,7 @@ module Conflow
22
25
  end
23
26
  end
24
27
 
28
+ # Setter uses Field#overwrite method to replace contents of the field
25
29
  def define_setter(field_name)
26
30
  define_method("#{field_name}=") do |value|
27
31
  send(field_name).tap { |field| field.overwrite(value) }
@@ -29,13 +33,19 @@ module Conflow
29
33
  end
30
34
  end
31
35
 
32
- attr_reader :field_name, :klass
36
+ # Name of the accessor methods
37
+ attr_reader :field_name
38
+ # Class of the field. Should inherit from {Conflow::Redis::Field}
39
+ attr_reader :klass
33
40
 
41
+ # @see field_name
42
+ # @see klass
34
43
  def initialize(field_name, klass)
35
44
  @field_name = field_name
36
45
  @klass = klass
37
46
  end
38
47
 
48
+ # Creates dynamic {FieldAccessor} module and includes it in base class
39
49
  def call(base, methods: %i[getter setter])
40
50
  base.include(FieldAccessor.new(field_name, klass, methods))
41
51
  end
@@ -3,12 +3,15 @@
3
3
  module Conflow
4
4
  module Redis
5
5
  # Findable module allows to use .find method on models with identifiers. It requires additional field: :type
6
+ # @api private
6
7
  module Findable
8
+ # Adds :type field to store class name of the Findable object
7
9
  def self.included(base)
8
10
  base.extend ClassMethods
9
11
  base.field :type, :value
10
12
  end
11
13
 
14
+ # Adds logic for assigning class name as type
12
15
  def initialize(*args)
13
16
  super
14
17
  self.type = self.class.name
@@ -16,6 +19,10 @@ module Conflow
16
19
 
17
20
  # Adds .find method which accepts ID and returns model of proper (sub)type
18
21
  module ClassMethods
22
+ # Creates new {Findable} object from ID.
23
+ # @example
24
+ # MyFlow.new.id #=> 13
25
+ # Conflow::Flow.find(13) #=> Myflow object
19
26
  def find(id)
20
27
  class_name = ValueField.new(format(key_template + ":type", id: id)).value
21
28
  raise ::Redis::CommandError, "#{name} with ID #{id} doesn't exist" unless class_name
@@ -3,26 +3,26 @@
3
3
  module Conflow
4
4
  module Redis
5
5
  # Represents Redis hash. It's methods mirror most used Hash methods.
6
+ # @api private
6
7
  class HashField < Field
7
8
  include Enumerable
8
9
 
9
- def [](field)
10
- value = command(:hget, [key, field])
11
- value ? JSON.parse(value) : value
12
- end
13
-
14
- def []=(field, value)
15
- command :hset, [key, field, JSON.dump(value)]
16
- end
17
-
10
+ # Merges hashes, similar to Hash#merge
11
+ # @param hash [Hash] hash of keys and values to be merged
12
+ # @return [String] Redis response
13
+ #
14
+ # @example
15
+ # field.merge(smart: true, degree: :none)
18
16
  def merge(hash)
19
17
  command :hmset, [key, hash.flatten]
20
18
  end
21
19
 
22
- def delete(*fields)
23
- command :hdel, [key, fields]
24
- end
25
-
20
+ # Replaces currently stored hash with one given as param
21
+ # @param new_hash [Hash] hash of keys and values to be stored
22
+ # @return [String] Redis response
23
+ #
24
+ # @example
25
+ # field.overwrite(smart: true, degree: :none)
26
26
  def overwrite(new_hash)
27
27
  redis.with do |conn|
28
28
  conn.pipelined do
@@ -32,24 +32,26 @@ module Conflow
32
32
  end
33
33
  end
34
34
 
35
- def keys
36
- command(:hkeys, [key]).map(&:to_sym)
37
- end
38
-
39
- def size
40
- command :hlen, [key]
41
- end
42
-
35
+ # Creates Ruby Hash based on soted values. Keys will be symbolized and values JSON-parsed
36
+ # @return [String] Redis response
37
+ #
38
+ # @example
39
+ # field.to_h #=> { smart: true, degree: "none" }
43
40
  def to_h
44
41
  command(:hgetall, [key]).each_with_object({}) do |(key, value), hash|
45
42
  hash[key.to_sym] = JSON.parse(value)
46
43
  end
47
44
  end; alias to_hash to_h
48
45
 
46
+ # Iterates over hash.
47
+ # @see to_h
48
+ # @return [Enumerator] if no block given
49
49
  def each(&block)
50
50
  to_h.each(&block)
51
51
  end
52
52
 
53
+ # @param other [Object] Object to compare value with. Handles Hashes and other {HashField} objects
54
+ # @return [Boolean] true if equal
53
55
  def ==(other)
54
56
  case other
55
57
  when Hash then to_h == other
@@ -58,6 +60,7 @@ module Conflow
58
60
  end
59
61
  end
60
62
 
63
+ # @return [String] string representation of the hash
61
64
  def to_s
62
65
  to_h.to_s
63
66
  end
@@ -5,6 +5,7 @@ module Conflow
5
5
  # Identifier changes logic of fields so that they can be found by an id.
6
6
  # ID is a counter stored in redis under .counter_key
7
7
  # Key is build with template stored in .key_template
8
+ # @api private
8
9
  module Identifier
9
10
  # Extends base class with {ClassMethods}
10
11
  def self.included(base)
@@ -13,7 +14,10 @@ module Conflow
13
14
 
14
15
  # class methods for classes with identifier
15
16
  module ClassMethods
16
- attr_writer :counter_key, :key_template
17
+ # @see counter_key
18
+ attr_writer :counter_key
19
+ # @see key_template
20
+ attr_writer :key_template
17
21
 
18
22
  # Copies *counter_key* and *key_template* to child classes
19
23
  def inherited(base)
@@ -3,6 +3,7 @@
3
3
  module Conflow
4
4
  module Redis
5
5
  # Models adds .field method which allows to define fields easily.
6
+ # @api private
6
7
  module Model
7
8
  # Extends base class with .field and .has_many methods
8
9
  def self.included(base)
@@ -3,6 +3,7 @@
3
3
  module Conflow
4
4
  module Redis
5
5
  # Removes jobs from indegree set, adds them to queued list, and returns IDs of queued jobs.
6
+ # @api private
6
7
  class QueueJobsScript < Script
7
8
  self.script = <<~LUA
8
9
  local indegree_set = KEYS[1]
@@ -3,6 +3,7 @@
3
3
  module Conflow
4
4
  module Redis
5
5
  # Main class for scripts, handling logic of executing and caching scripts.
6
+ # @api private
6
7
  class Script
7
8
  class << self
8
9
  # @return [Boolean] whether scripts are cached or not
@@ -3,6 +3,7 @@
3
3
  module Conflow
4
4
  module Redis
5
5
  # Represents Redis list. It's methods mirror most used Set methods.
6
+ # @api private
6
7
  class SetField < Field
7
8
  include Enumerable
8
9
 
@@ -4,6 +4,7 @@ module Conflow
4
4
  module Redis
5
5
  # Represents Redis sorted set. Closest Ruby representation is a Hash
6
6
  # where keys are elements of the set and values represent score.
7
+ # @api private
7
8
  class SortedSetField < Field
8
9
  # Adds one or more keys to the set.
9
10
  # @param hash [Hash] hash of values and scores to be added
@@ -25,17 +26,6 @@ module Conflow
25
26
  command :zscore, [key, value]
26
27
  end
27
28
 
28
- # Set score of given element.
29
- # @param value [String, Symbol] element of the set
30
- # @param rank [Numeric] score to be assigned
31
- # @return [Integer] Number of added elements (1 if key didn't exist, 0 otherwise)
32
- #
33
- # @example
34
- # field[:last] = 24 #=> 0
35
- def []=(value, rank)
36
- command :zadd, [key, rank, value]
37
- end
38
-
39
29
  # Number of elements in the set
40
30
  # @return [Integer] Size of the set
41
31
  #
@@ -55,22 +45,6 @@ module Conflow
55
45
  command :zrem, [key, value]
56
46
  end
57
47
 
58
- # Returns first *n* elements of the sorted set
59
- # @param num [Integer] amount of elements to be returned. Defaults to 1.
60
- # @return [String, Array<String>] first *num* elements from the set
61
- def first(num = 1)
62
- result = command :zrange, [key, 0, num - 1]
63
- num == 1 ? result[0] : result
64
- end
65
-
66
- # Returns last *n* elements of the sorted set
67
- # @param num [Integer] amount of elements to be returned. Defaults to 1.
68
- # @return [String, Array<String>] last *num* elements from the set
69
- def last(num = 1)
70
- result = command :zrevrange, [key, 0, num - 1]
71
- num == 1 ? result[0] : result
72
- end
73
-
74
48
  # Creates regular Ruby Hash based on Redis values.
75
49
  # @return [Hash] Hash representing this Sorted set
76
50
  def to_h
@@ -3,6 +3,7 @@
3
3
  module Conflow
4
4
  module Redis
5
5
  # Represents single value (Redis String). Values are serialized as JSON in order to preserve type.
6
+ # @api private
6
7
  class ValueField < Field
7
8
  # @note *value* must be serializable through JSON.dump
8
9
  # @param value [Object] new value to be saved
@@ -20,7 +21,7 @@ module Conflow
20
21
 
21
22
  # @param other [Object] Object to compare value with. Handles Strings, Numerics,
22
23
  # Symbols and other {ValueField} objects
23
- # @return [String] Redis response
24
+ # @return [Boolean] true if equal
24
25
  def ==(other)
25
26
  case other
26
27
  when String, Numeric then value == other
@@ -2,5 +2,5 @@
2
2
 
3
3
  module Conflow
4
4
  # Current version of the gem
5
- VERSION = "0.2.0"
5
+ VERSION = "0.3.0"
6
6
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: conflow
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michał Begejowicz
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-03-11 00:00:00.000000000 Z
11
+ date: 2018-03-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: redis
@@ -148,6 +148,7 @@ files:
148
148
  - lib/conflow/flow.rb
149
149
  - lib/conflow/flow/job_handler.rb
150
150
  - lib/conflow/job.rb
151
+ - lib/conflow/redis.rb
151
152
  - lib/conflow/redis/add_job_script.rb
152
153
  - lib/conflow/redis/array_field.rb
153
154
  - lib/conflow/redis/complete_job_script.rb