basket 0.0.1 → 0.0.3

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: 20ae2ec64c54d8a1ae452a284e20f8bc2393318f7333bcbc7152bf24236e4b26
4
- data.tar.gz: 8cb26c727cbc2c49ea906a6f949c6b1a8631a9bea3200b446f7ee2b4a8c15a59
3
+ metadata.gz: '092352c400ad4483af38e9afe1060a39c6162c7318e4c69fb1ecd7649af56344'
4
+ data.tar.gz: 9a6cb3e5937d7367b6e83bae58e796c71c7a2a7b77cec5bbbbd5178bf4e0107b
5
5
  SHA512:
6
- metadata.gz: 7f0b0410eb3ad97c9ca857e875c031d5d0bbee7183f62dc22d087424d503c16b2f5c7080aa1f458b89a07719eace55fae46b87f6df079cc8a4cc341b8a00f17a
7
- data.tar.gz: a6924dd3d2e1b3d3b731cbcbe2fa473718785244e432fd87a9de11e29a3f0275380581dbf5844a5e0d7bbbb6377a262e6592a657f0f1df5d5f0517f0697869ed
6
+ metadata.gz: a0f510f3e3f9c7b7accff0b76580d426e939d82212d6a4d83979f3043e4d679c8fafe994e58f788cf920110f3094e45cac1e290b50c802a22a5937358cdabd86
7
+ data.tar.gz: 33798eb722f92da71a396bac9529676f34cde316cdf3824fe5c42e66cfca26444caedb615fdcbad4ff67374a0a60dd646daf93eb349e0ee4d880f22b2186b2be
data/Gemfile CHANGED
@@ -5,8 +5,12 @@ source "https://rubygems.org"
5
5
  # Specify your gem's dependencies in basket.gemspec
6
6
  gemspec
7
7
 
8
+ gem "guard"
9
+ gem "guard-rspec", require: false
10
+ gem "guard-standardrb", require: false
11
+ gem "mocktail"
8
12
  gem "rake", "~> 13.0"
9
-
10
13
  gem "rspec", "~> 3.0"
11
-
14
+ gem "simplecov", require: false, group: :test
15
+ gem "simplecov-json", require: false, group: :test
12
16
  gem "standard", "~> 1.3"
data/Gemfile.lock CHANGED
@@ -1,20 +1,69 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- basket (0.1.0)
4
+ basket (0.0.2)
5
+ redis
6
+ redis-namespace
5
7
 
6
8
  GEM
7
9
  remote: https://rubygems.org/
8
10
  specs:
9
11
  ast (2.4.2)
12
+ coderay (1.1.3)
13
+ connection_pool (2.3.0)
10
14
  diff-lcs (1.5.0)
15
+ docile (1.4.0)
16
+ ffi (1.15.5)
17
+ formatador (1.1.0)
18
+ guard (2.18.0)
19
+ formatador (>= 0.2.4)
20
+ listen (>= 2.7, < 4.0)
21
+ lumberjack (>= 1.0.12, < 2.0)
22
+ nenv (~> 0.1)
23
+ notiffany (~> 0.0)
24
+ pry (>= 0.13.0)
25
+ shellany (~> 0.0)
26
+ thor (>= 0.18.1)
27
+ guard-compat (1.2.1)
28
+ guard-rspec (4.7.3)
29
+ guard (~> 2.1)
30
+ guard-compat (~> 1.1)
31
+ rspec (>= 2.99.0, < 4.0)
32
+ guard-standardrb (0.2.2)
33
+ guard (>= 2.0.0)
34
+ guard-compat (~> 1.0)
35
+ standardrb
11
36
  json (2.6.3)
12
37
  language_server-protocol (3.17.0.3)
38
+ listen (3.8.0)
39
+ rb-fsevent (~> 0.10, >= 0.10.3)
40
+ rb-inotify (~> 0.9, >= 0.9.10)
41
+ lumberjack (1.2.8)
42
+ method_source (1.0.0)
43
+ mock_redis (0.36.0)
44
+ ruby2_keywords
45
+ mocktail (1.2.2)
46
+ nenv (0.3.0)
47
+ notiffany (0.1.3)
48
+ nenv (~> 0.1)
49
+ shellany (~> 0.0)
13
50
  parallel (1.22.1)
14
51
  parser (3.2.1.0)
15
52
  ast (~> 2.4.1)
53
+ pry (0.14.2)
54
+ coderay (~> 1.1)
55
+ method_source (~> 1.0)
16
56
  rainbow (3.1.1)
17
57
  rake (13.0.6)
58
+ rb-fsevent (0.11.2)
59
+ rb-inotify (0.10.1)
60
+ ffi (~> 1.0)
61
+ redis (5.0.6)
62
+ redis-client (>= 0.9.0)
63
+ redis-client (0.14.0)
64
+ connection_pool
65
+ redis-namespace (1.10.0)
66
+ redis (>= 4)
18
67
  regexp_parser (2.7.0)
19
68
  rexml (3.2.5)
20
69
  rspec (3.12.0)
@@ -46,21 +95,43 @@ GEM
46
95
  rubocop (>= 1.7.0, < 2.0)
47
96
  rubocop-ast (>= 0.4.0)
48
97
  ruby-progressbar (1.11.0)
98
+ ruby2_keywords (0.0.5)
99
+ shellany (0.0.1)
100
+ simplecov (0.22.0)
101
+ docile (~> 1.1)
102
+ simplecov-html (~> 0.11)
103
+ simplecov_json_formatter (~> 0.1)
104
+ simplecov-html (0.12.3)
105
+ simplecov-json (0.2.3)
106
+ json
107
+ simplecov
108
+ simplecov_json_formatter (0.1.4)
49
109
  standard (1.24.3)
50
110
  language_server-protocol (~> 3.17.0.2)
51
111
  rubocop (= 1.44.1)
52
112
  rubocop-performance (= 1.15.2)
113
+ standardrb (1.0.1)
114
+ standard
115
+ thor (1.2.1)
53
116
  unicode-display_width (2.4.2)
54
117
 
55
118
  PLATFORMS
56
119
  arm64-darwin-22
57
120
  x86_64-darwin-20
121
+ x86_64-darwin-21
58
122
  x86_64-linux
59
123
 
60
124
  DEPENDENCIES
61
125
  basket!
126
+ guard
127
+ guard-rspec
128
+ guard-standardrb
129
+ mock_redis
130
+ mocktail
62
131
  rake (~> 13.0)
63
132
  rspec (~> 3.0)
133
+ simplecov
134
+ simplecov-json
64
135
  standard (~> 1.3)
65
136
 
66
137
  BUNDLED WITH
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: true, all_after_pass: true, cmd: "rspec" do
29
+ watch(%r{^spec/.+_spec\.rb$})
30
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
31
+ watch("spec/spec_helper.rb") { "spec/" }
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,25 @@
1
- # It would be silly to use this gem because it doesn't work yet.
1
+ [![Gem Version](https://badge.fury.io/rb/basket.svg)](https://badge.fury.io/rb/basket)
2
+ [![Ruby Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://github.com/testdouble/standard)
3
+ [![Tests](https://github.com/nicholalexander/basket/actions/workflows/main.yml/badge.svg)](https://github.com/nicholalexander/basket/actions/workflows/main.yml)
4
+ [![Maintainability](https://api.codeclimate.com/v1/badges/dab6a6e193cbd9df2b3e/maintainability)](https://codeclimate.com/github/nicholalexander/basket/maintainability)
5
+ [![Test Coverage](https://api.codeclimate.com/v1/badges/dab6a6e193cbd9df2b3e/test_coverage)](https://codeclimate.com/github/nicholalexander/basket/test_coverage)
2
6
  # Basket
3
7
 
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, etc, etc. 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.
8
+ 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
9
 
6
10
  `Basket` lets you do just that. Collect items until your basket is full and then, when it is, go do something with them!
7
11
 
8
- ## Installation
12
+ Basket is very new and under development.
9
13
 
10
- TODO: Replace `UPDATE_WITH_YOUR_GEM_NAME_PRIOR_TO_RELEASE_TO_RUBYGEMS_ORG` with your gem name right after releasing it to RubyGems.org. Please do not do it earlier due to security reasons. Alternatively, replace this section with instructions to install your gem from git if you don't plan to release to RubyGems.org.
14
+ ## Installation
11
15
 
12
16
  Install the gem and add to the application's Gemfile by executing:
13
17
 
14
- $ bundle add UPDATE_WITH_YOUR_GEM_NAME_PRIOR_TO_RELEASE_TO_RUBYGEMS_ORG
18
+ $ bundle add basket
15
19
 
16
20
  If bundler is not being used to manage dependencies, install the gem by executing:
17
21
 
18
- $ gem install UPDATE_WITH_YOUR_GEM_NAME_PRIOR_TO_RELEASE_TO_RUBYGEMS_ORG
22
+ $ gem install basket
19
23
 
20
24
  ## Usage
21
25
 
@@ -32,40 +36,71 @@ The item added to the basket can be any data you want! If you are using the in
32
36
 
33
37
  ```ruby
34
38
  class QuicheBasket
39
+ # Include the Basket::Batcher
35
40
  include Basket::Batcher
36
-
37
- basket_options length: 15
41
+
42
+ # Define the size of your basket
43
+ basket_options size: 15
38
44
 
39
45
  def perform
40
- eggs = []
41
46
  batch.each do | egg |
42
- # do some processing on each element of the batch. In this case there will be 15 eggs.
43
- egg = Egg.new(egg)
44
- egg.wash!
45
- eggs << egg
47
+ # Do some processing on each element of the batch. In this case there will be 15 eggs.
46
48
  end
47
49
 
48
50
  # If you want to do something directly inline:
49
- Quiche.make(eggs)
51
+ Quiche.make(batch)
50
52
 
51
53
  # If you want to do something out of a request response cycle,
52
54
  # call out to your favorite background processing framework:
53
55
  BrunchInviteJob.perform_async
54
56
  end
55
57
 
56
- # There are four callbacks to the lifecycle of a basket.
57
- # :on_success, :on_failure, :on_add, :check_length
58
+ # There are three callbacks to the lifecycle of a basket.
59
+ # :on_add, :on_success, and :on_failure.
58
60
  # They can be used like this:
59
- on_success: :let_chickens_rest
61
+ def on_success
62
+ Farm.rest_chickens
63
+ batch.each do |egg|
64
+ egg.inspect
65
+ end
66
+ end
60
67
 
61
- def let_chickens_rest
62
- ...
68
+ def on_add
69
+ element.wash
63
70
  end
64
71
 
72
+ def on_failure
73
+ Farm.notify_egg_monitor(error)
74
+ raise Error
75
+ end
76
+ end
77
+ ```
78
+
79
+ 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.
80
+
81
+ 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`.
82
+
83
+ 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.
84
+
85
+ Defining `on_add`, `on_failure`, and `on_success` is optional.
86
+
87
+ ## Configuration
88
+
89
+ In an initializer, or somewhere equally appropriate, you might put something like this:
90
+
91
+ ```ruby
92
+ Basket.config do |config|
93
+ config.redis_host = "127.0.0.2"
94
+ config.redis_port = 6390
95
+ config.redis_db = 10
96
+ config.backend = :redis
97
+ config.namespace = :basket
65
98
  end
66
99
  ```
67
100
 
68
- The perform method will be called after there have been 15 elements added to the batch. The callbacks are lifecycle callbacks on the existing batch. `on_add` takes an argument of the element that is being added. The elements are just a hash. `on_success` and `on_failure` give access to the whole batch.
101
+ The defaults for a redis backend are the standard "127.0.0.1", 6379, 15 with a namespace of :basket.
102
+
103
+ The default for the backend is the HashBackend, which can be set by passing `:hash` to `config.backend`, but you don't have to do that. Because it's the default!
69
104
 
70
105
  ## Development
71
106
 
@@ -73,9 +108,11 @@ After checking out the repo, run `bin/setup` to install dependencies. Then, run
73
108
 
74
109
  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
110
 
111
+ 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.
112
+
76
113
  ## Contributing
77
114
 
78
- 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).
115
+ Bug reports and pull requests are welcome on GitHub at https://github.com/nicholalexander/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/nicholalexander/basket/blob/main/CODE_OF_CONDUCT.md).
79
116
 
80
117
  ## License
81
118
 
@@ -83,26 +120,7 @@ The gem is available as open source under the terms of the [MIT License](https:/
83
120
 
84
121
  ## Code of Conduct
85
122
 
86
- Everyone interacting in the Basket project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/basket/blob/main/CODE_OF_CONDUCT.md).
87
-
88
-
89
-
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.
123
+ Everyone interacting in the Basket project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/nicholalexander/basket/blob/main/CODE_OF_CONDUCT.md).
105
124
 
106
- https://api.rubyonrails.org/classes/ActiveSupport/Callbacks.html
107
125
 
108
126
 
data/basket.gemspec CHANGED
@@ -5,11 +5,11 @@ require_relative "lib/basket/version"
5
5
  Gem::Specification.new do |spec|
6
6
  spec.name = "basket"
7
7
  spec.version = Basket::VERSION
8
- spec.authors = ["nichol alexander"]
9
- spec.email = ["nichol.alexander@gmail.com "]
8
+ spec.authors = ["nichol alexander", "alec clarke"]
9
+ spec.email = ["nichol.alexander@gmail.com", "alec.clarke.dev@gmail.com"]
10
10
 
11
11
  spec.summary = "Wait until you have a bunch of things, then do something."
12
- spec.description = "This is a longer description."
12
+ spec.description = "A simple way of accumulating things and then acting on them."
13
13
  spec.homepage = "https://github.com/nicholalexander/basket"
14
14
  spec.license = "MIT"
15
15
  spec.required_ruby_version = ">= 2.6.0"
@@ -18,8 +18,6 @@ Gem::Specification.new do |spec|
18
18
  spec.metadata["source_code_uri"] = "https://github.com/nicholalexander/basket"
19
19
  spec.metadata["changelog_uri"] = "https://github.com/nicholalexander/basket/blob/main/CHANGELOG.md"
20
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
21
  spec.files = Dir.chdir(__dir__) do
24
22
  `git ls-files -z`.split("\x0").reject do |f|
25
23
  (f == __FILE__) || f.match(%r{\A(?:(?:bin|test|spec|features)/|\.(?:git|circleci)|appveyor)})
@@ -29,9 +27,8 @@ Gem::Specification.new do |spec|
29
27
  spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
30
28
  spec.require_paths = ["lib"]
31
29
 
32
- # Uncomment to register a new dependency of your gem
33
- # spec.add_dependency "example-gem", "~> 1.0"
30
+ spec.add_dependency "redis"
31
+ spec.add_dependency "redis-namespace"
34
32
 
35
- # For more information and examples about making a new gem, check out our
36
- # guide at: https://bundler.io/guides/creating_gem.html
33
+ spec.add_development_dependency "mock_redis"
37
34
  end
@@ -0,0 +1,30 @@
1
+ module Basket
2
+ class BackendAdapter
3
+ class HashBackend < Basket::BackendAdapter
4
+ def initialize
5
+ @data = {}
6
+ end
7
+
8
+ attr_reader :data
9
+
10
+ def push(queue, data)
11
+ @data[queue] = [] if @data[queue].nil?
12
+ @data[queue] <<= data
13
+ end
14
+
15
+ def length(queue)
16
+ return 0 if @data[queue].nil?
17
+
18
+ @data[queue].length
19
+ end
20
+
21
+ def read(queue)
22
+ @data[queue]
23
+ end
24
+
25
+ def clear(queue)
26
+ @data[queue] = []
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,56 @@
1
+ require "redis-namespace"
2
+
3
+ module Basket
4
+ class BackendAdapter
5
+ class RedisBackend < Basket::BackendAdapter
6
+ attr_reader :client
7
+
8
+ def initialize
9
+ redis_connection = Redis.new(
10
+ host: Basket.config.redis_host,
11
+ port: Basket.config.redis_port,
12
+ db: Basket.config.redis_db
13
+ )
14
+
15
+ @client = Redis::Namespace.new(
16
+ Basket.config.namespace,
17
+ redis: redis_connection
18
+ )
19
+ end
20
+
21
+ def data
22
+ response = {}
23
+
24
+ @client.scan_each do |queue|
25
+ response[queue] = deserialized_queue_data(queue)
26
+ end
27
+
28
+ response
29
+ end
30
+
31
+ def push(queue, data)
32
+ # TODO: should we use JSON vs Marshal?
33
+ marshalled_data = Marshal.dump(data)
34
+ @client.lpush(queue, marshalled_data)
35
+ end
36
+
37
+ def length(queue)
38
+ @client.llen(queue)
39
+ end
40
+
41
+ def clear(queue)
42
+ @client.del(queue)
43
+ end
44
+
45
+ def read(queue)
46
+ deserialized_queue_data(queue)
47
+ end
48
+
49
+ private
50
+
51
+ def deserialized_queue_data(queue)
52
+ @client.lrange(queue, 0, -1).reverse.map { |marshalled_data| Marshal.load(marshalled_data) }
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,23 @@
1
+ module Basket
2
+ class BackendAdapter
3
+ def data
4
+ raise "must implement data"
5
+ end
6
+
7
+ def push(queue, data)
8
+ raise "must implement push with queue and data params"
9
+ end
10
+
11
+ def length(queue)
12
+ raise "must implement length with queue param"
13
+ end
14
+
15
+ def read(queue)
16
+ raise "must implement read with queue param"
17
+ end
18
+
19
+ def clear(queue)
20
+ raise "must implement clear with queue param"
21
+ end
22
+ end
23
+ end
@@ -1,4 +1,38 @@
1
1
  module Basket
2
2
  module Batcher
3
+ def self.included(base)
4
+ base.extend(ClassMethods)
5
+ end
6
+
7
+ module ClassMethods
8
+ def basket_options(args)
9
+ @basket_options = args
10
+ end
11
+
12
+ def basket_options_hash
13
+ raise Basket::Error, "You must specify the size of your basket!" if @basket_options.nil?
14
+ raise Basket::Error, "You must specify a size greater than 0" if @basket_options[:size] <= 0
15
+
16
+ @basket_options
17
+ end
18
+ end
19
+
20
+ def batch
21
+ @batch ||= Basket.queue_collection.read(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
@@ -0,0 +1,25 @@
1
+ module Basket
2
+ class Configuration
3
+ attr_accessor :redis_host, :redis_port, :redis_db, :namespace
4
+ attr_reader :backend
5
+
6
+ def initialize
7
+ @redis_host = "127.0.0.1"
8
+ @redis_port = 6379
9
+ @redis_db = 15
10
+ @backend = BackendAdapter::HashBackend
11
+ @namespace = :basket
12
+ end
13
+
14
+ def backend=(backend)
15
+ case backend
16
+ when :hash
17
+ @backend = BackendAdapter::HashBackend
18
+ when :redis
19
+ @backend = BackendAdapter::RedisBackend
20
+ else
21
+ raise Basket::Error, "Unknown Backend"
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,5 @@
1
+ module Basket
2
+ class Error < StandardError; end
3
+
4
+ class BasketNotFoundError < Error; end
5
+ end
@@ -0,0 +1,49 @@
1
+ module Basket
2
+ class HandleAdd
3
+ def self.call(queue, data)
4
+ new(queue, data).call
5
+ end
6
+
7
+ def initialize(queue, data)
8
+ @queue = queue
9
+ @data = data
10
+ @queue_collection = Basket.queue_collection
11
+ end
12
+
13
+ def call(data = @data)
14
+ queue_length = @queue_collection.push(@queue, data)
15
+ queue_class = class_for_queue
16
+ queue_instance = queue_class.new
17
+
18
+ queue_instance.define_singleton_method(:element) { data }
19
+ queue_instance.on_add
20
+
21
+ return unless basket_full?(queue_length, queue_class)
22
+
23
+ queue_instance.perform
24
+ queue_instance.on_success
25
+ @queue_collection.clear(@queue)
26
+ rescue => e
27
+ raise e if basket_error?(e)
28
+
29
+ queue_instance.define_singleton_method(:error) { e }
30
+ queue_instance.on_failure
31
+ end
32
+
33
+ private
34
+
35
+ def class_for_queue
36
+ Object.const_get(@queue)
37
+ rescue NameError => e
38
+ raise Basket::BasketNotFoundError, "We couldn't find that basket anywhere, please make sure it is defined. | #{e.message}"
39
+ end
40
+
41
+ def basket_full?(queue_length, queue_class)
42
+ queue_length == queue_class.basket_options_hash[:size]
43
+ end
44
+
45
+ def basket_error?(e)
46
+ e.instance_of?(Basket::Error) || e.instance_of?(Basket::BasketNotFoundError)
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,32 @@
1
+ module Basket
2
+ class QueueCollection
3
+ def initialize(backend = Basket.config.backend)
4
+ @backend = backend.new
5
+ end
6
+
7
+ def push(queue, data)
8
+ @backend.push(queue, data)
9
+ length(queue)
10
+ end
11
+
12
+ def length(queue)
13
+ @backend.length(queue)
14
+ end
15
+
16
+ def read(queue)
17
+ @backend.read(queue)
18
+ end
19
+
20
+ def clear(queue)
21
+ @backend.clear(queue)
22
+ end
23
+
24
+ def data
25
+ @backend.data
26
+ end
27
+
28
+ def reset_backend
29
+ @backend = Basket.config.backend.new
30
+ end
31
+ end
32
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Basket
4
- VERSION = "0.0.1"
4
+ VERSION = "0.0.3"
5
5
  end
data/lib/basket.rb CHANGED
@@ -1,18 +1,39 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative "basket/backend_adapter"
4
+ require_relative "basket/backend_adapter/hash_backend"
5
+ require_relative "basket/backend_adapter/redis_backend"
3
6
  require_relative "basket/batcher"
4
- require_relative "basket/hash_backend"
5
- require_relative "basket/queue"
7
+ require_relative "basket/configuration"
8
+ require_relative "basket/error"
9
+ require_relative "basket/handle_add"
10
+ require_relative "basket/queue_collection"
6
11
  require_relative "basket/version"
7
12
 
8
13
  module Basket
9
14
  class Error < StandardError; end
10
15
 
16
+ def self.config
17
+ @config ||= Configuration.new
18
+ end
19
+
20
+ def self.configure
21
+ yield(config)
22
+ end
23
+
24
+ def self.contents
25
+ @queue_collection.data
26
+ end
27
+
28
+ def self.queue_collection
29
+ @queue_collection ||= Basket::QueueCollection.new
30
+ end
31
+
11
32
  def self.add(queue, data)
12
- queue_length = Basket::Queue.push(queue, data)
13
- queue_class = queue.constantize.new
14
- return unless queue_length == queue_class.batcher.options.queue_length
33
+ HandleAdd.call(queue, data)
34
+ end
15
35
 
16
- queue_class.perform
36
+ def self.clear_all
37
+ queue_collection.reset_backend
17
38
  end
18
39
  end
metadata CHANGED
@@ -1,18 +1,62 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: basket
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - nichol alexander
8
+ - alec clarke
8
9
  autorequire:
9
10
  bindir: exe
10
11
  cert_chain: []
11
- date: 2023-02-18 00:00:00.000000000 Z
12
- dependencies: []
13
- description: This is a longer description.
12
+ date: 2023-03-26 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: redis
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ">="
19
+ - !ruby/object:Gem::Version
20
+ version: '0'
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ version: '0'
28
+ - !ruby/object:Gem::Dependency
29
+ name: redis-namespace
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: '0'
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ - !ruby/object:Gem::Dependency
43
+ name: mock_redis
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ description: A simple way of accumulating things and then acting on them.
14
57
  email:
15
- - 'nichol.alexander@gmail.com '
58
+ - nichol.alexander@gmail.com
59
+ - alec.clarke.dev@gmail.com
16
60
  executables: []
17
61
  extensions: []
18
62
  extra_rdoc_files: []
@@ -23,14 +67,20 @@ files:
23
67
  - CODE_OF_CONDUCT.md
24
68
  - Gemfile
25
69
  - Gemfile.lock
70
+ - Guardfile
26
71
  - LICENSE.txt
27
72
  - README.md
28
73
  - Rakefile
29
74
  - basket.gemspec
30
75
  - lib/basket.rb
76
+ - lib/basket/backend_adapter.rb
77
+ - lib/basket/backend_adapter/hash_backend.rb
78
+ - lib/basket/backend_adapter/redis_backend.rb
31
79
  - lib/basket/batcher.rb
32
- - lib/basket/hash_backend.rb
33
- - lib/basket/queue.rb
80
+ - lib/basket/configuration.rb
81
+ - lib/basket/error.rb
82
+ - lib/basket/handle_add.rb
83
+ - lib/basket/queue_collection.rb
34
84
  - lib/basket/version.rb
35
85
  - sig/basket.rbs
36
86
  homepage: https://github.com/nicholalexander/basket
@@ -1,24 +0,0 @@
1
- module Basket
2
- class HashBackend
3
- attr_reader :data
4
-
5
- def initialize
6
- @data = {}
7
- end
8
-
9
- def push(queue, data)
10
- @data[queue] = [] if @data[queue].nil?
11
- @data[queue] <<= data
12
- end
13
-
14
- def length(queue)
15
- return 0 if @data[queue].nil?
16
-
17
- @data[queue].length
18
- end
19
-
20
- def pop_all(queue)
21
- @data.delete(queue)
22
- end
23
- end
24
- end
data/lib/basket/queue.rb DELETED
@@ -1,24 +0,0 @@
1
- module Basket
2
- class Queue
3
- def initialize(backend = HashBackend.new)
4
- @backend = backend
5
- end
6
-
7
- def push(queue, data)
8
- @backend.push(queue, data)
9
- length(queue)
10
- end
11
-
12
- def length(queue)
13
- @backend.length(queue)
14
- end
15
-
16
- def pop_all(queue)
17
- @backend.pop_all(queue)
18
- end
19
-
20
- def data
21
- @backend.data
22
- end
23
- end
24
- end