fluq 0.7.5 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (83) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/.travis.yml +3 -0
  4. data/Gemfile +12 -1
  5. data/Gemfile.lock +44 -8
  6. data/README.md +24 -6
  7. data/Rakefile +8 -1
  8. data/benchmark/socket.rb +13 -25
  9. data/examples/config/multi.rb +52 -0
  10. data/examples/config/simple.rb +15 -0
  11. data/fluq.gemspec +3 -3
  12. data/lib/fluq.rb +22 -16
  13. data/lib/fluq/cli.rb +3 -12
  14. data/lib/fluq/dsl.rb +2 -45
  15. data/lib/fluq/dsl/base.rb +11 -0
  16. data/lib/fluq/dsl/feed.rb +24 -0
  17. data/lib/fluq/dsl/root.rb +35 -0
  18. data/lib/fluq/event.rb +9 -28
  19. data/lib/fluq/feed.rb +40 -5
  20. data/lib/fluq/format.rb +6 -0
  21. data/lib/fluq/format/base.rb +42 -0
  22. data/lib/fluq/format/json.rb +17 -0
  23. data/lib/fluq/format/lines.rb +27 -0
  24. data/lib/fluq/format/msgpack.rb +28 -0
  25. data/lib/fluq/format/tsv.rb +19 -0
  26. data/lib/fluq/handler.rb +1 -1
  27. data/lib/fluq/handler/base.rb +11 -38
  28. data/lib/fluq/handler/log.rb +12 -14
  29. data/lib/fluq/handler/noop.rb +2 -0
  30. data/lib/fluq/input/base.rb +33 -29
  31. data/lib/fluq/input/socket.rb +46 -16
  32. data/lib/fluq/mixins.rb +2 -2
  33. data/lib/fluq/runner.rb +41 -0
  34. data/lib/fluq/testing.rb +5 -11
  35. data/lib/fluq/version.rb +1 -1
  36. data/lib/fluq/worker.rb +73 -0
  37. data/spec/fluq/dsl/feed_spec.rb +33 -0
  38. data/spec/fluq/dsl/root_spec.rb +20 -0
  39. data/spec/fluq/event_spec.rb +17 -12
  40. data/spec/fluq/feed_spec.rb +24 -0
  41. data/spec/fluq/format/base_spec.rb +9 -0
  42. data/spec/fluq/format/json_spec.rb +22 -0
  43. data/spec/fluq/format/lines_spec.rb +20 -0
  44. data/spec/fluq/format/msgpack_spec.rb +22 -0
  45. data/spec/fluq/format/tsv_spec.rb +21 -0
  46. data/spec/fluq/handler/base_spec.rb +7 -52
  47. data/spec/fluq/handler/log_spec.rb +11 -14
  48. data/spec/fluq/handler/{null_spec.rb → noop_spec.rb} +1 -3
  49. data/spec/fluq/input/base_spec.rb +48 -15
  50. data/spec/fluq/input/socket_spec.rb +34 -26
  51. data/spec/fluq/mixins/loggable_spec.rb +2 -2
  52. data/spec/fluq/runner_spec.rb +18 -0
  53. data/spec/fluq/worker_spec.rb +87 -0
  54. data/spec/fluq_spec.rb +1 -2
  55. data/spec/scenario/config/nested/feed1.rb +6 -0
  56. data/spec/scenario/config/test.rb +8 -2
  57. data/spec/spec_helper.rb +7 -26
  58. metadata +62 -62
  59. data/benchmark/logging.rb +0 -37
  60. data/examples/common.rb +0 -3
  61. data/examples/simple.rb +0 -5
  62. data/lib/fluq/buffer.rb +0 -6
  63. data/lib/fluq/buffer/base.rb +0 -51
  64. data/lib/fluq/buffer/file.rb +0 -68
  65. data/lib/fluq/feed/base.rb +0 -37
  66. data/lib/fluq/feed/json.rb +0 -28
  67. data/lib/fluq/feed/msgpack.rb +0 -27
  68. data/lib/fluq/feed/tsv.rb +0 -30
  69. data/lib/fluq/handler/null.rb +0 -4
  70. data/lib/fluq/input/socket/connection.rb +0 -41
  71. data/lib/fluq/mixins/logger.rb +0 -26
  72. data/lib/fluq/reactor.rb +0 -79
  73. data/spec/fluq/buffer/base_spec.rb +0 -21
  74. data/spec/fluq/buffer/file_spec.rb +0 -47
  75. data/spec/fluq/dsl_spec.rb +0 -43
  76. data/spec/fluq/feed/base_spec.rb +0 -15
  77. data/spec/fluq/feed/json_spec.rb +0 -27
  78. data/spec/fluq/feed/msgpack_spec.rb +0 -27
  79. data/spec/fluq/feed/tsv_spec.rb +0 -27
  80. data/spec/fluq/input/socket/connection_spec.rb +0 -35
  81. data/spec/fluq/mixins/logger_spec.rb +0 -25
  82. data/spec/fluq/reactor_spec.rb +0 -69
  83. data/spec/scenario/config/nested/common.rb +0 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: dd0315737359aba13bf67dc4ac588f57a12fedb4
4
- data.tar.gz: 0f5456c2087986cd3a80561c9d756cafe05b52ca
3
+ metadata.gz: 7820b9f9dfe9f91d1e8b3939363fa6471b2b233e
4
+ data.tar.gz: 3f8c2e1c3160e2db2f6f1f2c78496b759c536bd1
5
5
  SHA512:
6
- metadata.gz: 01a1b080eb885a520b7517cda04157d8374f02b232ed09175a0345cb5259320c91242f3d223d06731f73cb0d11b0fc62fc35aa9b8d4dca0b2c5ff649431892f4
7
- data.tar.gz: d6eac4e626670db21f1b3b89949924b74ab0a2e2ab74571b8a388d37904e9eeb6887e71cc73e42bb8f90fbc8620c11304b50b49e31f9e0c2a6e9047835a8a69c
6
+ metadata.gz: d5292f948e9c5b97d13acfd6822778586f812c7a40ab19122cf59b476443246ae5276f1eea07fb6daad9ce344edc70fe0f9873624e376910fe9513cf6a27ae5a
7
+ data.tar.gz: 486b08a58d7aaabf5c73af6ab525aec4b743079fa45247907c34b1c8d78dc1e47e5199436bec376f733c9cfad5f7713663c329c060ac40c7c4d7f9e26d406e38
data/.gitignore CHANGED
@@ -1,3 +1,5 @@
1
1
  log/
2
2
  tmp/
3
3
  *.gem
4
+ .bundle
5
+ coverage/
data/.travis.yml CHANGED
@@ -2,5 +2,8 @@ language: ruby
2
2
  rvm:
3
3
  - 1.9.3
4
4
  - 2.0.0
5
+ - 2.1.0
6
+ - jruby-19mode
5
7
  gemfile:
6
8
  - Gemfile
9
+ script: bundle exec rake spec:coveralls
data/Gemfile CHANGED
@@ -1,6 +1,17 @@
1
1
  source "https://rubygems.org"
2
2
  gemspec
3
3
 
4
- group :development do
4
+ platform :ruby do
5
5
  gem "oj"
6
+ gem "msgpack"
7
+ end
8
+
9
+ platform :jruby do
10
+ gem "jrjackson"
11
+ gem "msgpack-jruby"
12
+ end
13
+
14
+ platform :rbx do
15
+ gem "rubysl-logger"
16
+ gem "rubysl-singleton"
6
17
  end
data/Gemfile.lock CHANGED
@@ -1,20 +1,38 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- fluq (0.7.5)
5
- eventmachine-le
6
- msgpack (~> 0.5.0)
7
- oj (>= 2.0.10)
4
+ fluq (0.8.0)
5
+ celluloid-io (~> 0.15.0)
6
+ multi_json
8
7
  timed_lru
9
8
 
10
9
  GEM
11
10
  remote: https://rubygems.org/
12
11
  specs:
12
+ celluloid (0.15.2)
13
+ timers (~> 1.1.0)
14
+ celluloid-io (0.15.0)
15
+ celluloid (>= 0.15.0)
16
+ nio4r (>= 0.5.0)
17
+ coveralls (0.7.0)
18
+ multi_json (~> 1.3)
19
+ rest-client
20
+ simplecov (>= 0.7)
21
+ term-ansicolor
22
+ thor
13
23
  diff-lcs (1.2.5)
14
- eventmachine-le (1.1.6)
15
- msgpack (0.5.7)
16
- oj (2.2.2)
17
- rake (10.1.0)
24
+ docile (1.1.2)
25
+ jrjackson (0.2.6)
26
+ mime-types (2.1)
27
+ msgpack (0.5.8)
28
+ msgpack-jruby (1.3.2-java)
29
+ multi_json (1.8.4)
30
+ nio4r (1.0.0)
31
+ nio4r (1.0.0-java)
32
+ oj (2.5.4)
33
+ rake (10.1.1)
34
+ rest-client (1.6.7)
35
+ mime-types (>= 1.16)
18
36
  rspec (2.14.1)
19
37
  rspec-core (~> 2.14.0)
20
38
  rspec-expectations (~> 2.14.0)
@@ -23,7 +41,19 @@ GEM
23
41
  rspec-expectations (2.14.4)
24
42
  diff-lcs (>= 1.1.3, < 2.0)
25
43
  rspec-mocks (2.14.4)
44
+ rubysl-logger (2.0.0)
45
+ rubysl-singleton (2.0.0)
46
+ simplecov (0.8.2)
47
+ docile (~> 1.1.0)
48
+ multi_json
49
+ simplecov-html (~> 0.8.0)
50
+ simplecov-html (0.8.0)
51
+ term-ansicolor (1.2.2)
52
+ tins (~> 0.8)
53
+ thor (0.18.1)
26
54
  timed_lru (0.3.1)
55
+ timers (1.1.0)
56
+ tins (0.13.1)
27
57
  yard (0.8.7.3)
28
58
 
29
59
  PLATFORMS
@@ -32,8 +62,14 @@ PLATFORMS
32
62
 
33
63
  DEPENDENCIES
34
64
  bundler
65
+ coveralls
35
66
  fluq!
67
+ jrjackson
68
+ msgpack
69
+ msgpack-jruby
36
70
  oj
37
71
  rake
38
72
  rspec
73
+ rubysl-logger
74
+ rubysl-singleton
39
75
  yard
data/README.md CHANGED
@@ -1,10 +1,28 @@
1
- FluQ
2
- ====
1
+ # FluQ [![Build Status](https://travis-ci.org/bsm/fluq.png?branch=master)](https://travis-ci.org/bsm/fluq) [![Coverage Status](https://coveralls.io/repos/bsm/fluq/badge.png)](https://coveralls.io/r/bsm/fluq)
3
2
 
4
3
  Description coming soon ...
5
4
 
6
- Licence
7
- -------
5
+ ## Licence
8
6
 
9
- Copyright 2013 Black Square Media Ltd.
10
- It is free software, and may be redistributed under the terms specified in the MIT-LICENCE file.
7
+ ```
8
+ Copyright (c) 2014 Black Square Media
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining
11
+ a copy of this software and associated documentation files (the
12
+ "Software"), to deal in the Software without restriction, including
13
+ without limitation the rights to use, copy, modify, merge, publish,
14
+ distribute, sublicense, and/or sell copies of the Software, and to
15
+ permit persons to whom the Software is furnished to do so, subject to
16
+ the following conditions:
17
+
18
+ The above copyright notice and this permission notice shall be
19
+ included in all copies or substantial portions of the Software.
20
+
21
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28
+ ```
data/Rakefile CHANGED
@@ -1,11 +1,18 @@
1
1
  require 'rake'
2
+ require 'bundler/gem_tasks'
2
3
 
3
- require 'rspec/mocks/version'
4
4
  require 'rspec/core/rake_task'
5
5
  RSpec::Core::RakeTask.new(:spec)
6
6
 
7
7
  require 'yard'
8
+ require 'yard/rake/yardoc_task'
8
9
  YARD::Rake::YardocTask.new
9
10
 
11
+ require 'coveralls/rake/task'
12
+ Coveralls::RakeTask.new
13
+ namespace :spec do
14
+ task coveralls: [:spec, 'coveralls:push']
15
+ end
16
+
10
17
  desc 'Default: run specs.'
11
18
  task :default => :spec
data/benchmark/socket.rb CHANGED
@@ -8,45 +8,33 @@ require 'fluq'
8
8
  BATCH_SIZE = 100_000
9
9
  BATCHES = 50
10
10
  ROOT = FluQ.root.join("log/benchmark")
11
- EVENT = FluQ::Event.new("a.b.c.d", Time.now.to_i, "k1" => "value", "k2" => "value", "k3" => "value").to_msgpack
11
+ EVENT = MessagePack.pack("k1" => "value", "k2" => "value", "k3" => "value")
12
12
 
13
13
  FileUtils.rm_rf ROOT.to_s
14
14
  FileUtils.mkdir_p ROOT.to_s
15
+ FluQ.logger.level = Logger::ERROR
15
16
 
16
- class FluQ::Handler::Counter < FluQ::Handler::Base
17
- attr_reader :count
18
- def initialize(*)
19
- super
20
- @count = 0
21
- end
22
- def on_events(events)
23
- @count += events.size
24
- EM.stop if @count >= BATCHES * BATCH_SIZE
17
+ puts "--> Preparing"
18
+ Thread.new do
19
+ FluQ::Runner.run do |run|
20
+ run.feed :test do |feed|
21
+ feed.register FluQ::Handler::Noop
22
+ feed.listen FluQ::Input::Socket, bind: "tcp://127.0.0.1:8765", format: :msgpack
23
+ end
25
24
  end
26
25
  end
27
-
28
- puts "--> Preparing"
29
26
  BATCHES.times do |i|
30
27
  ROOT.join("batch.#{i}").open("wb:ASCII-8BIT") do |file|
31
28
  BATCH_SIZE.times { file.write(EVENT) }
32
29
  end
33
30
  end
34
31
 
35
- processed = 0
36
- handler = nil
37
- start = Time.now
38
- FluQ::Reactor.run do |reactor|
39
- reactor.listen FluQ::Input::Socket, bind: "tcp://127.0.0.1:8765"
40
- handler = reactor.register FluQ::Handler::Counter
41
-
42
- sleep(0.1)
32
+ puts "--> Started benchmark"
33
+ 2.times do
43
34
  start = Time.now
44
- puts "--> Started benchmark"
45
35
  BATCHES.times do |i|
46
36
  file = ROOT.join("batch.#{i}")
47
- spawn("nc 127.0.0.1 8765 < #{file}")
37
+ system "nc 127.0.0.1 8765 < #{file}"
48
38
  end
39
+ puts "--> Processed : #{BATCHES * BATCH_SIZE} in #{(Time.now - start).round(1)}s"
49
40
  end
50
-
51
- puts "--> Accepted : #{BATCHES * BATCH_SIZE} in #{(Time.now - start).round(1)}s"
52
- puts "--> Processed : #{handler.count} events"
@@ -0,0 +1,52 @@
1
+ # Main feed
2
+ feed "main" do
3
+
4
+ # Listen on a UDP socket
5
+ input :socket do
6
+ bind "udp://127.0.0.1:6789"
7
+ format :json
8
+ end
9
+
10
+ # Log all events to a path
11
+ handler :log do
12
+ path "/var/log/main/%Y%m%d/%H.log"
13
+ end
14
+
15
+ end
16
+
17
+ # Priority feed
18
+ feed "priority" do
19
+
20
+ # Listen on a TCP socket
21
+ input :socket do
22
+ bind "tcp://127.0.0.1:6789"
23
+ format :json
24
+ end
25
+
26
+ # Pull Kafka topic (requires fluq-kafka Gem)
27
+ input :kafka do
28
+ topic "orders"
29
+ brokers ["host1:9092", "host2:9092"]
30
+ zookeepers ["host1:2181", "host2:2181"]
31
+ format :msgpack
32
+ end
33
+
34
+ # Pull another Kafka topic
35
+ input :kafka do
36
+ topic "deliveries"
37
+ brokers ["host1:9092", "host2:9092"]
38
+ zookeepers ["host1:2181", "host2:2181"]
39
+ format :msgpack
40
+ end
41
+
42
+ # Log all events to a path
43
+ handler :log do
44
+ path "/var/log/priority/%Y%m%d/%H.log"
45
+ end
46
+
47
+ # Use your own custom handler to e.g. send notification emails
48
+ handler :email do
49
+ to "relevant.party@example.com"
50
+ end
51
+
52
+ end
@@ -0,0 +1,15 @@
1
+ # Feed definition: a feed 'wraps' a list of inputs and a list of handler
2
+ feed "my-feed" do
3
+
4
+ # Listen on a TCP socket for JSON formatted messages
5
+ input :socket do
6
+ bind "tcp://127.0.0.1:6789"
7
+ format :json
8
+ end
9
+
10
+ # Log all events to a timestamped path
11
+ handler :log do
12
+ path "/var/log/%Y%m%d/%H.log"
13
+ end
14
+
15
+ end
data/fluq.gemspec CHANGED
@@ -22,13 +22,13 @@ Gem::Specification.new do |s|
22
22
  s.files = `git ls-files`.split("\n")
23
23
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
24
24
 
25
- s.add_dependency "msgpack", "~> 0.5.0"
26
- s.add_dependency "eventmachine-le"
27
- s.add_dependency "oj", ">= 2.0.10"
25
+ s.add_dependency "celluloid-io", "~> 0.15.0"
28
26
  s.add_dependency "timed_lru"
27
+ s.add_dependency "multi_json"
29
28
 
30
29
  s.add_development_dependency "rake"
31
30
  s.add_development_dependency "bundler"
32
31
  s.add_development_dependency "rspec"
33
32
  s.add_development_dependency "yard"
33
+ s.add_development_dependency "coveralls"
34
34
  end
data/lib/fluq.rb CHANGED
@@ -1,14 +1,21 @@
1
1
  require 'pathname'
2
2
  require 'uri'
3
3
  require 'fileutils'
4
+ require 'stringio'
5
+ require 'thread'
4
6
  require 'securerandom'
5
7
  require 'forwardable'
6
8
  require 'logger'
7
- require 'eventmachine'
8
- require 'msgpack'
9
- require 'oj'
10
- require 'timed_lru'
11
9
  require 'timeout'
10
+ require 'timed_lru'
11
+ require 'celluloid/io'
12
+ require 'celluloid/autostart'
13
+ require 'multi_json'
14
+
15
+ begin
16
+ require 'msgpack'
17
+ rescue LoadError
18
+ end
12
19
 
13
20
  module FluQ
14
21
  %w'version error mixins'.each do |name|
@@ -17,27 +24,26 @@ module FluQ
17
24
 
18
25
  class << self
19
26
 
20
- # @attr_reader [String] env runtime environemnt
21
27
  # @attr_reader [Pathname] root project root
22
- # @attr_reader [Logger] logger the main logger
23
- attr_reader :env, :root, :logger
28
+ attr_reader :root
24
29
 
25
- # @param [Logger] instance the thread-safe logger instance
26
- def logger=(instance)
27
- instance.extend(FluQ::Mixins::Logger)
28
- @logger = instance
30
+ # @param [Logger] logger
31
+ def logger=(logger)
32
+ Celluloid.logger = logger
29
33
  end
30
34
 
31
- def init!
32
- # Detect environment
33
- @env = ENV['FLUQ_ENV'] || "development"
35
+ # @return [Logger] the thread-safe logger instance
36
+ def logger
37
+ Celluloid.logger
38
+ end
34
39
 
40
+ def init!
35
41
  # Set root path
36
42
  @root = Pathname.new(ENV['FLUQ_ROOT'] || ".")
37
43
 
38
44
  # Setup logger
39
45
  self.logger = ::Logger.new(STDOUT)
40
- logger.level = ::Logger::INFO if env == "production"
46
+ logger.level = ::Logger::INFO
41
47
  end
42
48
  protected :init!
43
49
 
@@ -46,6 +52,6 @@ module FluQ
46
52
  init!
47
53
  end
48
54
 
49
- %w'url event reactor handler input buffer feed dsl'.each do |name|
55
+ %w'url event runner feed worker handler input format dsl'.each do |name|
50
56
  require "fluq/#{name}"
51
57
  end
data/lib/fluq/cli.rb CHANGED
@@ -33,11 +33,6 @@ module FluQ
33
33
  exit
34
34
  end
35
35
 
36
- # Set the environment
37
- if options[:env]
38
- ENV["FLUQ_ENV"] = options[:env]
39
- end
40
-
41
36
  # Boot and add project's lib/ dir to load path
42
37
  require 'fluq'
43
38
  $LOAD_PATH.unshift FluQ.root.join('lib')
@@ -63,9 +58,9 @@ module FluQ
63
58
  end
64
59
 
65
60
  # Start
66
- log "Starting FluQ #{FluQ::VERSION} (#{FluQ.env})"
67
- FluQ::Reactor.run do |reactor|
68
- FluQ::DSL.new(reactor, options[:config]).run
61
+ log "Starting FluQ #{FluQ::VERSION} (#{options[:config]})"
62
+ FluQ::Runner.run do |runner|
63
+ FluQ::DSL::Root.new(options[:config]).apply(runner)
69
64
  procline
70
65
  end
71
66
  end
@@ -106,10 +101,6 @@ module FluQ
106
101
  o.separator ""
107
102
  o.separator "Optional:"
108
103
 
109
- o.on("-e", "--environment ENV", "Runtime environment (default: development)") do |val|
110
- @options[:env] = val
111
- end
112
-
113
104
  o.on("-l", "--log FILE", "File to log to (default: STDOUT)") do |val|
114
105
  @options[:log] = val
115
106
  end
data/lib/fluq/dsl.rb CHANGED
@@ -1,49 +1,6 @@
1
- class FluQ::DSL
2
- attr_reader :path, :reactor, :inputs, :handlers
3
-
4
- # @param [FluQ::Reactor] reactor
5
- # @param [String] DSL script file path
6
- def initialize(reactor, path)
7
- @reactor = reactor
8
- @path = Pathname.new(path)
9
- @inputs = []
10
- @handlers = []
11
- end
12
-
13
- # @param [Array<Symbol>] input type path, e.g. :socket
14
- def input(*type, &block)
15
- klass = constantize(:input, *type)
16
- inputs.push [klass, FluQ::DSL::Options.new(&block).to_hash]
17
- end
18
-
19
- # @param [Array<Symbol>] handler type path, e.g. :log, :counter
20
- def handler(*type, &block)
21
- klass = constantize(:handler, *type)
22
- handlers.push [klass, FluQ::DSL::Options.new(&block).to_hash]
23
- end
24
-
25
- # @param [String] relative relative path
26
- def import(relative)
27
- instance_eval(path.dirname.join(relative).read)
28
- end
29
-
30
- # Starts the components. Handlers first, then inputs.
31
- def run
32
- instance_eval(path.read)
33
- handlers.each {|klass, options| reactor.register(klass, options) }
34
- inputs.each {|klass, options| reactor.listen(klass, options) }
35
- end
36
-
37
- protected
38
-
39
- def constantize(*path)
40
- require([:fluq, *path].join('/'))
41
- names = path.map {|p| p.to_s.split('_').map(&:capitalize).join }
42
- names.inject(FluQ) {|klass, name| klass.const_get(name) }
43
- end
44
-
1
+ module FluQ::DSL
45
2
  end
46
3
 
47
- %w'options'.each do |name|
4
+ %w'base root feed options'.each do |name|
48
5
  require "fluq/dsl/#{name}"
49
6
  end