basket 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +5 -0
- data/Gemfile.lock +47 -1
- data/Guardfile +37 -0
- data/README.md +34 -38
- data/lib/basket/batcher.rb +34 -0
- data/lib/basket/configuration.rb +7 -0
- data/lib/basket/error.rb +4 -0
- data/lib/basket/{queue.rb → queue_collection.rb} +5 -1
- data/lib/basket/version.rb +1 -1
- data/lib/basket.rb +30 -5
- metadata +7 -5
- data/basket.gemspec +0 -37
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d11f37f0087fb606bf92362eb1c913e9f089b262d130a13edfb22d639055c374
|
4
|
+
data.tar.gz: b66835a0ad01af6b29b528a2e7bd481331e64b0b437586a42a504ecc27d3c1b7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f015621c801d42ef33fc3090d244b8a53f8a8830d7230ce73177287ba9b7ab3a7fe41129a6427c66a1119e17e0fb75e1be82bfbca0424026bdbefb0d33e94a79
|
7
|
+
data.tar.gz: 4ae3e63475e3fb68e2177356d44f5a92b332b31efe43081c76f3df5824751f4ed3d203b39f3d01e227edea063466220e9ec4bd63a6cb272f8f560fbb70c31ce9
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,20 +1,57 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
basket (0.
|
4
|
+
basket (0.0.2)
|
5
5
|
|
6
6
|
GEM
|
7
7
|
remote: https://rubygems.org/
|
8
8
|
specs:
|
9
9
|
ast (2.4.2)
|
10
|
+
coderay (1.1.3)
|
10
11
|
diff-lcs (1.5.0)
|
12
|
+
ffi (1.15.5)
|
13
|
+
formatador (1.1.0)
|
14
|
+
guard (2.18.0)
|
15
|
+
formatador (>= 0.2.4)
|
16
|
+
listen (>= 2.7, < 4.0)
|
17
|
+
lumberjack (>= 1.0.12, < 2.0)
|
18
|
+
nenv (~> 0.1)
|
19
|
+
notiffany (~> 0.0)
|
20
|
+
pry (>= 0.13.0)
|
21
|
+
shellany (~> 0.0)
|
22
|
+
thor (>= 0.18.1)
|
23
|
+
guard-compat (1.2.1)
|
24
|
+
guard-rspec (4.7.3)
|
25
|
+
guard (~> 2.1)
|
26
|
+
guard-compat (~> 1.1)
|
27
|
+
rspec (>= 2.99.0, < 4.0)
|
28
|
+
guard-standardrb (0.2.2)
|
29
|
+
guard (>= 2.0.0)
|
30
|
+
guard-compat (~> 1.0)
|
31
|
+
standardrb
|
11
32
|
json (2.6.3)
|
12
33
|
language_server-protocol (3.17.0.3)
|
34
|
+
listen (3.8.0)
|
35
|
+
rb-fsevent (~> 0.10, >= 0.10.3)
|
36
|
+
rb-inotify (~> 0.9, >= 0.9.10)
|
37
|
+
lumberjack (1.2.8)
|
38
|
+
method_source (1.0.0)
|
39
|
+
mocktail (1.2.2)
|
40
|
+
nenv (0.3.0)
|
41
|
+
notiffany (0.1.3)
|
42
|
+
nenv (~> 0.1)
|
43
|
+
shellany (~> 0.0)
|
13
44
|
parallel (1.22.1)
|
14
45
|
parser (3.2.1.0)
|
15
46
|
ast (~> 2.4.1)
|
47
|
+
pry (0.14.2)
|
48
|
+
coderay (~> 1.1)
|
49
|
+
method_source (~> 1.0)
|
16
50
|
rainbow (3.1.1)
|
17
51
|
rake (13.0.6)
|
52
|
+
rb-fsevent (0.11.2)
|
53
|
+
rb-inotify (0.10.1)
|
54
|
+
ffi (~> 1.0)
|
18
55
|
regexp_parser (2.7.0)
|
19
56
|
rexml (3.2.5)
|
20
57
|
rspec (3.12.0)
|
@@ -46,19 +83,28 @@ GEM
|
|
46
83
|
rubocop (>= 1.7.0, < 2.0)
|
47
84
|
rubocop-ast (>= 0.4.0)
|
48
85
|
ruby-progressbar (1.11.0)
|
86
|
+
shellany (0.0.1)
|
49
87
|
standard (1.24.3)
|
50
88
|
language_server-protocol (~> 3.17.0.2)
|
51
89
|
rubocop (= 1.44.1)
|
52
90
|
rubocop-performance (= 1.15.2)
|
91
|
+
standardrb (1.0.1)
|
92
|
+
standard
|
93
|
+
thor (1.2.1)
|
53
94
|
unicode-display_width (2.4.2)
|
54
95
|
|
55
96
|
PLATFORMS
|
56
97
|
arm64-darwin-22
|
57
98
|
x86_64-darwin-20
|
99
|
+
x86_64-darwin-21
|
58
100
|
x86_64-linux
|
59
101
|
|
60
102
|
DEPENDENCIES
|
61
103
|
basket!
|
104
|
+
guard
|
105
|
+
guard-rspec
|
106
|
+
guard-standardrb
|
107
|
+
mocktail
|
62
108
|
rake (~> 13.0)
|
63
109
|
rspec (~> 3.0)
|
64
110
|
standard (~> 1.3)
|
data/Guardfile
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
# A sample Guardfile
|
2
|
+
# More info at https://github.com/guard/guard#readme
|
3
|
+
|
4
|
+
## Uncomment and set this to only include directories you want to watch
|
5
|
+
# directories %w(app lib config test spec features) \
|
6
|
+
# .select{|d| Dir.exist?(d) ? d : UI.warning("Directory #{d} does not exist")}
|
7
|
+
|
8
|
+
## Note: if you are using the `directories` clause above and you are not
|
9
|
+
## watching the project directory ('.'), then you will want to move
|
10
|
+
## the Guardfile to a watched dir and symlink it back, e.g.
|
11
|
+
#
|
12
|
+
# $ mkdir config
|
13
|
+
# $ mv Guardfile config/
|
14
|
+
# $ ln -s config/Guardfile .
|
15
|
+
#
|
16
|
+
# and, you'll have to watch "config/Guardfile" instead of "Guardfile"
|
17
|
+
|
18
|
+
# Note: The cmd option is now required due to the increasing number of ways
|
19
|
+
# rspec may be run, below are examples of the most common uses.
|
20
|
+
# * bundler: 'bundle exec rspec'
|
21
|
+
# * bundler binstubs: 'bin/rspec'
|
22
|
+
# * spring: 'bin/rspec' (This will use spring if running and you have
|
23
|
+
# installed the spring binstubs per the docs)
|
24
|
+
# * zeus: 'zeus rspec' (requires the server to be started separately)
|
25
|
+
# * 'just' rspec: 'rspec'
|
26
|
+
|
27
|
+
group "specs", halt_on_fail: true do
|
28
|
+
guard :rspec, all_on_start: false, cmd: "rspec" do
|
29
|
+
watch(%r{^spec/.+_spec\.rb$})
|
30
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
|
31
|
+
watch("spec/spec_helper.rb") { "spec/lib" }
|
32
|
+
end
|
33
|
+
|
34
|
+
guard :standardrb, fix: true, all_on_start: true, progress: true do
|
35
|
+
watch(/.+\.rb$/)
|
36
|
+
end
|
37
|
+
end
|
data/README.md
CHANGED
@@ -1,21 +1,21 @@
|
|
1
|
-
|
1
|
+
[![Gem Version](https://badge.fury.io/rb/basket.svg)](https://badge.fury.io/rb/basket)
|
2
2
|
# Basket
|
3
3
|
|
4
|
-
A farmer doesn't walk down to the chicken coop, grab an egg, go back to the kitchen, go back to the coop, go back to the kitchen
|
4
|
+
A farmer doesn't walk down to the chicken coop, grab an egg, go back to the kitchen, go back to the coop, go back to the kitchen ad infinitum. They take a basket with them, and as the chickens lay their eggs, they fill up the basket and when the basket is full they go make something with them! I would make a quiche, but that's besides the case.
|
5
5
|
|
6
6
|
`Basket` lets you do just that. Collect items until your basket is full and then, when it is, go do something with them!
|
7
7
|
|
8
|
-
|
8
|
+
Basket is very new and under development.
|
9
9
|
|
10
|
-
|
10
|
+
## Installation
|
11
11
|
|
12
12
|
Install the gem and add to the application's Gemfile by executing:
|
13
13
|
|
14
|
-
$ bundle add
|
14
|
+
$ bundle add basket
|
15
15
|
|
16
16
|
If bundler is not being used to manage dependencies, install the gem by executing:
|
17
17
|
|
18
|
-
$ gem install
|
18
|
+
$ gem install basket
|
19
19
|
|
20
20
|
## Usage
|
21
21
|
|
@@ -32,21 +32,19 @@ The item added to the basket can be any data you want! If you are using the in
|
|
32
32
|
|
33
33
|
```ruby
|
34
34
|
class QuicheBasket
|
35
|
+
# Include the Basket::Batcher
|
35
36
|
include Basket::Batcher
|
36
|
-
|
37
|
-
|
37
|
+
|
38
|
+
# Define the size of your basket
|
39
|
+
basket_options size: 15
|
38
40
|
|
39
41
|
def perform
|
40
|
-
eggs = []
|
41
42
|
batch.each do | egg |
|
42
|
-
#
|
43
|
-
egg = Egg.new(egg)
|
44
|
-
egg.wash!
|
45
|
-
eggs << egg
|
43
|
+
# Do some processing on each element of the batch. In this case there will be 15 eggs.
|
46
44
|
end
|
47
45
|
|
48
46
|
# If you want to do something directly inline:
|
49
|
-
Quiche.make(
|
47
|
+
Quiche.make(batch)
|
50
48
|
|
51
49
|
# If you want to do something out of a request response cycle,
|
52
50
|
# call out to your favorite background processing framework:
|
@@ -54,18 +52,33 @@ class QuicheBasket
|
|
54
52
|
end
|
55
53
|
|
56
54
|
# There are four callbacks to the lifecycle of a basket.
|
57
|
-
# :
|
55
|
+
# :on_add, :on_success, and :on_failure.
|
58
56
|
# They can be used like this:
|
59
|
-
on_success
|
57
|
+
def on_success
|
58
|
+
Farm.rest_chickens
|
59
|
+
batch.each do |egg|
|
60
|
+
egg.inspect
|
61
|
+
end
|
62
|
+
end
|
60
63
|
|
61
|
-
def
|
62
|
-
|
64
|
+
def on_add
|
65
|
+
element.wash
|
63
66
|
end
|
64
67
|
|
68
|
+
def on_failure
|
69
|
+
Farm.notify_egg_monitor(error)
|
70
|
+
raise Error
|
71
|
+
end
|
65
72
|
end
|
66
73
|
```
|
67
74
|
|
68
|
-
The perform method will be called after there have been
|
75
|
+
The perform method will be called after there have been the defined number of elements added to the batch, specified in the `basket_options` size parameter. The elements can be any kind of data, depending on the backend that you are using. The default is just an in-memory hash.
|
76
|
+
|
77
|
+
The callbacks are lifecycle callbacks on the existing batch. `on_add` gives access to a variable called `element` which is equal to the item just added to the batch. `on_add`, `on_success` and `on_failure` also give access to the whole batch through the `batch` variable. `on_success` is called after `perform`.
|
78
|
+
|
79
|
+
The `on_failure` use of `batch` of course may not have a full batch as the error could have been generated during `add` or `on_add`. The `on_failure` callback also has access to an `error` variable which holds the error that was generated.
|
80
|
+
|
81
|
+
Defining `on_add`, `on_failure`, and `on_success` is optional.
|
69
82
|
|
70
83
|
## Development
|
71
84
|
|
@@ -73,6 +86,8 @@ After checking out the repo, run `bin/setup` to install dependencies. Then, run
|
|
73
86
|
|
74
87
|
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 the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
75
88
|
|
89
|
+
This project uses Guard to facilitate local development. You can run it with `bundle exec guard`. It will run specs on change to files and will run `standard --fix` after passing tests.
|
90
|
+
|
76
91
|
## Contributing
|
77
92
|
|
78
93
|
Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/basket. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/[USERNAME]/basket/blob/main/CODE_OF_CONDUCT.md).
|
@@ -87,22 +102,3 @@ Everyone interacting in the Basket project's codebases, issue trackers, chat roo
|
|
87
102
|
|
88
103
|
|
89
104
|
|
90
|
-
## Ideas
|
91
|
-
|
92
|
-
1. Can the callbacks support ActiveSupport Notifications?
|
93
|
-
- ActiveSupport::Callbacks extraction of callbacks
|
94
|
-
2. Batch can be postgres json blob or Redis! - Backend system
|
95
|
-
~~3. Does not execute in line~~For now.
|
96
|
-
~~4. Use ActiveJob for background execution.~~ It's up to you to handle a full basket how you want.
|
97
|
-
~~5. "Buffer", "collection", "queue"~~ Basket.
|
98
|
-
6. Default trigger is just queue length.
|
99
|
-
7. Expose basket_options trigger: :check_some_thing_lambda
|
100
|
-
8. Redis push pop.
|
101
|
-
9. Make queue ephemeral?
|
102
|
-
10. Define gotchas but don't solve them.
|
103
|
-
11. Redis fetch / Super Fetch?
|
104
|
-
12. Configuration.
|
105
|
-
|
106
|
-
https://api.rubyonrails.org/classes/ActiveSupport/Callbacks.html
|
107
|
-
|
108
|
-
|
data/lib/basket/batcher.rb
CHANGED
@@ -1,4 +1,38 @@
|
|
1
|
+
require_relative "./error"
|
1
2
|
module Basket
|
2
3
|
module Batcher
|
4
|
+
def self.included(base)
|
5
|
+
base.extend(ClassMethods)
|
6
|
+
end
|
7
|
+
|
8
|
+
module ClassMethods
|
9
|
+
def basket_options(args)
|
10
|
+
@basket_options = args
|
11
|
+
end
|
12
|
+
|
13
|
+
def basket_options_hash
|
14
|
+
raise Basket::Error, "You must specify the size of your basket!" if @basket_options.nil?
|
15
|
+
raise Basket::Error, "You must specify a size greater than 0" if @basket_options[:size] <= 0
|
16
|
+
@basket_options
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def batch
|
21
|
+
@batch ||= Basket.config.queue_collection.pop_all(self.class.name)
|
22
|
+
end
|
23
|
+
|
24
|
+
def perform
|
25
|
+
raise Basket::Error, "You must implement perform in your Basket class."
|
26
|
+
end
|
27
|
+
|
28
|
+
def on_success
|
29
|
+
end
|
30
|
+
|
31
|
+
def on_add
|
32
|
+
end
|
33
|
+
|
34
|
+
def on_failure
|
35
|
+
raise error
|
36
|
+
end
|
3
37
|
end
|
4
38
|
end
|
data/lib/basket/error.rb
ADDED
@@ -1,5 +1,5 @@
|
|
1
1
|
module Basket
|
2
|
-
class
|
2
|
+
class QueueCollection
|
3
3
|
def initialize(backend = HashBackend.new)
|
4
4
|
@backend = backend
|
5
5
|
end
|
@@ -20,5 +20,9 @@ module Basket
|
|
20
20
|
def data
|
21
21
|
@backend.data
|
22
22
|
end
|
23
|
+
|
24
|
+
def reset_backend
|
25
|
+
@backend = HashBackend.new
|
26
|
+
end
|
23
27
|
end
|
24
28
|
end
|
data/lib/basket/version.rb
CHANGED
data/lib/basket.rb
CHANGED
@@ -1,18 +1,43 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative "basket/batcher"
|
4
|
+
require_relative "basket/configuration"
|
5
|
+
require_relative "basket/error"
|
4
6
|
require_relative "basket/hash_backend"
|
5
|
-
require_relative "basket/
|
7
|
+
require_relative "basket/queue_collection"
|
6
8
|
require_relative "basket/version"
|
7
9
|
|
8
10
|
module Basket
|
9
11
|
class Error < StandardError; end
|
10
12
|
|
13
|
+
def self.config
|
14
|
+
@config ||= Configuration.new
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.contents
|
18
|
+
@queue_collection.data
|
19
|
+
end
|
20
|
+
|
11
21
|
def self.add(queue, data)
|
12
|
-
|
13
|
-
|
14
|
-
|
22
|
+
@queue_collection = config.queue_collection
|
23
|
+
queue_length = @queue_collection.push(queue, data)
|
24
|
+
queue_class = Object.const_get(queue)
|
25
|
+
queue_instance = queue_class.new
|
26
|
+
|
27
|
+
queue_instance.define_singleton_method(:element) { data }
|
28
|
+
queue_instance.on_add
|
29
|
+
|
30
|
+
return unless queue_length == queue_class.basket_options_hash[:size]
|
31
|
+
|
32
|
+
queue_instance.perform
|
33
|
+
queue_instance.on_success
|
34
|
+
rescue => e
|
35
|
+
raise e if e.instance_of?(Basket::Error)
|
36
|
+
queue_instance.define_singleton_method(:error) { e }
|
37
|
+
queue_instance.on_failure
|
38
|
+
end
|
15
39
|
|
16
|
-
|
40
|
+
def self.clear_all
|
41
|
+
config.queue_collection.reset_backend
|
17
42
|
end
|
18
43
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: basket
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- nichol alexander
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-03-05 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: This is a longer description.
|
14
14
|
email:
|
@@ -23,14 +23,16 @@ files:
|
|
23
23
|
- CODE_OF_CONDUCT.md
|
24
24
|
- Gemfile
|
25
25
|
- Gemfile.lock
|
26
|
+
- Guardfile
|
26
27
|
- LICENSE.txt
|
27
28
|
- README.md
|
28
29
|
- Rakefile
|
29
|
-
- basket.gemspec
|
30
30
|
- lib/basket.rb
|
31
31
|
- lib/basket/batcher.rb
|
32
|
+
- lib/basket/configuration.rb
|
33
|
+
- lib/basket/error.rb
|
32
34
|
- lib/basket/hash_backend.rb
|
33
|
-
- lib/basket/
|
35
|
+
- lib/basket/queue_collection.rb
|
34
36
|
- lib/basket/version.rb
|
35
37
|
- sig/basket.rbs
|
36
38
|
homepage: https://github.com/nicholalexander/basket
|
@@ -55,7 +57,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
55
57
|
- !ruby/object:Gem::Version
|
56
58
|
version: '0'
|
57
59
|
requirements: []
|
58
|
-
rubygems_version: 3.
|
60
|
+
rubygems_version: 3.3.24
|
59
61
|
signing_key:
|
60
62
|
specification_version: 4
|
61
63
|
summary: Wait until you have a bunch of things, then do something.
|
data/basket.gemspec
DELETED
@@ -1,37 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative "lib/basket/version"
|
4
|
-
|
5
|
-
Gem::Specification.new do |spec|
|
6
|
-
spec.name = "basket"
|
7
|
-
spec.version = Basket::VERSION
|
8
|
-
spec.authors = ["nichol alexander"]
|
9
|
-
spec.email = ["nichol.alexander@gmail.com "]
|
10
|
-
|
11
|
-
spec.summary = "Wait until you have a bunch of things, then do something."
|
12
|
-
spec.description = "This is a longer description."
|
13
|
-
spec.homepage = "https://github.com/nicholalexander/basket"
|
14
|
-
spec.license = "MIT"
|
15
|
-
spec.required_ruby_version = ">= 2.6.0"
|
16
|
-
|
17
|
-
spec.metadata["homepage_uri"] = spec.homepage
|
18
|
-
spec.metadata["source_code_uri"] = "https://github.com/nicholalexander/basket"
|
19
|
-
spec.metadata["changelog_uri"] = "https://github.com/nicholalexander/basket/blob/main/CHANGELOG.md"
|
20
|
-
|
21
|
-
# Specify which files should be added to the gem when it is released.
|
22
|
-
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
23
|
-
spec.files = Dir.chdir(__dir__) do
|
24
|
-
`git ls-files -z`.split("\x0").reject do |f|
|
25
|
-
(f == __FILE__) || f.match(%r{\A(?:(?:bin|test|spec|features)/|\.(?:git|circleci)|appveyor)})
|
26
|
-
end
|
27
|
-
end
|
28
|
-
spec.bindir = "exe"
|
29
|
-
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
30
|
-
spec.require_paths = ["lib"]
|
31
|
-
|
32
|
-
# Uncomment to register a new dependency of your gem
|
33
|
-
# spec.add_dependency "example-gem", "~> 1.0"
|
34
|
-
|
35
|
-
# For more information and examples about making a new gem, check out our
|
36
|
-
# guide at: https://bundler.io/guides/creating_gem.html
|
37
|
-
end
|