conflow 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +5 -5
- data/README.md +38 -2
- data/lib/conflow.rb +8 -0
- data/lib/conflow/flow/job_handler.rb +4 -1
- data/lib/conflow/redis.rb +8 -0
- data/lib/conflow/redis/add_job_script.rb +1 -0
- data/lib/conflow/redis/array_field.rb +13 -34
- data/lib/conflow/redis/complete_job_script.rb +1 -0
- data/lib/conflow/redis/connection_wrapper.rb +1 -0
- data/lib/conflow/redis/field.rb +3 -0
- data/lib/conflow/redis/field_builder.rb +11 -1
- data/lib/conflow/redis/findable.rb +7 -0
- data/lib/conflow/redis/hash_field.rb +24 -21
- data/lib/conflow/redis/identifier.rb +5 -1
- data/lib/conflow/redis/model.rb +1 -0
- data/lib/conflow/redis/queue_jobs_script.rb +1 -0
- data/lib/conflow/redis/script.rb +1 -0
- data/lib/conflow/redis/set_field.rb +1 -0
- data/lib/conflow/redis/sorted_set_field.rb +1 -27
- data/lib/conflow/redis/value_field.rb +2 -1
- data/lib/conflow/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 572a2e10d542d2914de25fc748c1c153938e59b081aaef7829208395a86e462b
|
4
|
+
data.tar.gz: 99a32aa33c314eeabfa4feed3b386072ba2146139b552b257c59cd4b693fcca0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
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.
|
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.
|
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.
|
49
|
-
docile (~> 1.1
|
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
|
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)
|
@@ -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
|
-
|
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
|
-
|
36
|
-
|
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
|
-
|
44
|
-
|
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
|
data/lib/conflow/redis/field.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
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
|
-
|
23
|
-
|
24
|
-
|
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
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
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
|
-
|
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)
|
data/lib/conflow/redis/model.rb
CHANGED
data/lib/conflow/redis/script.rb
CHANGED
@@ -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 [
|
24
|
+
# @return [Boolean] true if equal
|
24
25
|
def ==(other)
|
25
26
|
case other
|
26
27
|
when String, Numeric then value == other
|
data/lib/conflow/version.rb
CHANGED
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.
|
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
|
+
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
|