depth_first 1.0.2 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +72 -1
- data/lib/depth_first/parallel_organizer.rb +17 -0
- data/lib/depth_first/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f458b23b4e11951bfe32ce363890c693ad436c02a8a01c06d7a63f1e1d1310db
|
4
|
+
data.tar.gz: a5fbd2c177fd85f4fe5edf6b0dd46e1354ee94fd4de2a72cdb6c3f9a18b1c0f9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 32f4030a7a3cc8e214fbe1ae02a60ac77de467ae87725afc62cc3756cf39778d8c1719f92e813fe0cacfd99551ef8fc4745bee8f4cc160dbc7dbf48f2b00ad5f
|
7
|
+
data.tar.gz: a7e2ea90b8b5246d22352e75d94a78f354a15e9b686019dbab1206c95594b3750853818b25ef30cac01527ee714a4360f5e7a2b319bb839c5581e7e5fb29e8ea
|
data/README.md
CHANGED
@@ -1,2 +1,73 @@
|
|
1
1
|
# depth_first
|
2
|
-
Depth-first search code organization
|
2
|
+
Depth-first search code organization gem allowing for sequential and concurrent code execution using [concurrent-ruby](https://github.com/ruby-concurrency/concurrent-ruby).
|
3
|
+
|
4
|
+
## Tasks
|
5
|
+
A task accepts an input hash and merges in a results hash.
|
6
|
+
|
7
|
+
### Examples
|
8
|
+
```
|
9
|
+
class A < DepthFirst::Task
|
10
|
+
def perform
|
11
|
+
{ a: 1 }
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class B < DepthFirst::Task
|
16
|
+
def perform
|
17
|
+
{ b: 2 }
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class C < DepthFirst::Task
|
22
|
+
def perform
|
23
|
+
{ c: 3 }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
```
|
27
|
+
|
28
|
+
### Usage
|
29
|
+
```
|
30
|
+
> A.new(test: true).perform
|
31
|
+
=> { test: true, a: 1 }
|
32
|
+
|
33
|
+
> B.new(test: true).perform
|
34
|
+
=> { test: true, b: 2 }
|
35
|
+
```
|
36
|
+
|
37
|
+
## Organizers
|
38
|
+
An organizer chains together tasks, piping a hash through each subtask.
|
39
|
+
|
40
|
+
## SequentialOrganizer
|
41
|
+
Data is passed through `A`, `B`, and `C` sequentially. The input hash `{ testing: true }` is piped through A. The resulting hash `{ testing: true, a: 1 }` is then piped through B. And so on.
|
42
|
+
|
43
|
+
### Example
|
44
|
+
```
|
45
|
+
class SequentialAbc < DepthFirst::SequentialOrganizer
|
46
|
+
TASKS = [A, B, C].freeze
|
47
|
+
end
|
48
|
+
```
|
49
|
+
|
50
|
+
### Usage
|
51
|
+
```
|
52
|
+
> SequentialAbc.new(testing: true).perform
|
53
|
+
=> { testing: true, a: 1, b: 2, c: 3 }
|
54
|
+
```
|
55
|
+
|
56
|
+
## ParallelOrganizer
|
57
|
+
Data is passed through `A`, `B`, and `C` concurrently. All three classes execute in parallel. The input hash `{ testing: true }` is passed to all three classes and all three intermediate result hashes are merged into the final result hash once their promises are resolved.
|
58
|
+
|
59
|
+
### Example
|
60
|
+
```
|
61
|
+
class ParallelAbc < DepthFirst::ParallelOrganizer
|
62
|
+
TASKS = [A, B, C].freeze
|
63
|
+
end
|
64
|
+
```
|
65
|
+
|
66
|
+
### Usage
|
67
|
+
```
|
68
|
+
> ParallelAbc.new(testing: true).perform
|
69
|
+
=> { testing: true, a: 1, b: 2, c: 3}
|
70
|
+
```
|
71
|
+
|
72
|
+
## Note
|
73
|
+
An organizer can have a subtask which is itself another organizer. In this manner, code can be organized in an arbitrarily-deep tree structure with order of execution roughly matching a Depth First Search algorithm.
|
@@ -1,6 +1,13 @@
|
|
1
1
|
module DepthFirst
|
2
2
|
# Base parallel organizer class
|
3
3
|
class ParallelOrganizer < SequentialOrganizer
|
4
|
+
DEPENDENCIES = [].freeze
|
5
|
+
|
6
|
+
def initialize(options)
|
7
|
+
super(options)
|
8
|
+
load_dependencies
|
9
|
+
end
|
10
|
+
|
4
11
|
def perform
|
5
12
|
tasks.map { |task| execute_promise(task) }
|
6
13
|
.reduce(options) { |a, e| resolve_promise(a, e) }
|
@@ -8,6 +15,16 @@ module DepthFirst
|
|
8
15
|
|
9
16
|
private
|
10
17
|
|
18
|
+
# Load dependencies before concurrency to get
|
19
|
+
# around lazy-loading race condition.
|
20
|
+
def load_dependencies
|
21
|
+
dependencies.each { |dependency| dependency }
|
22
|
+
end
|
23
|
+
|
24
|
+
def dependencies
|
25
|
+
self.class::DEPENDENCIES
|
26
|
+
end
|
27
|
+
|
11
28
|
def execute_promise(task)
|
12
29
|
Concurrent::Promise.new { task.new(options).perform }.execute
|
13
30
|
end
|
data/lib/depth_first/version.rb
CHANGED