utracker-mongodb 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6681c9dc22f7c1e4da8144cf567f748e1bdfc61d
4
- data.tar.gz: b2764f1eb5460c2de25dfda57d975f1be16c9ba6
3
+ metadata.gz: 766bf8d7ee5c34e57bf403ad040952cb5f8d91ec
4
+ data.tar.gz: b592b42578fcc34b9f6a2d42c16590a6b4c9d847
5
5
  SHA512:
6
- metadata.gz: 86911d58dcb31ed8474b2ed60b7256a9e3bfc1e96b8191377a3431c559c69078fcf8449905c8366cffa1ff89cae46e48922e14ef86cea4ca60dce7f68a62286d
7
- data.tar.gz: f20705ed020be7a890933b4a746e8d518dba3138d88b99df8f8b7563775b2460e0279d7d1144d92289639be124ddc2d2591163b21a8ba3d72049f7ad77091488
6
+ metadata.gz: b43fee3b6fc379c10f36340a58038ea713a2b8c19e5675ed2d4d73c20b3fa457c7f7150e60dbe14a1594fd2d34459e8cdd686e0a84d7337d03c787b9e8c3a3ef
7
+ data.tar.gz: 8fe68fbf330be9659fb2776e22c87fef13ab18ccb4f0ca3dbffcc71bc1f2f34ea181ca16267bc76cbab53898d766972b76d7072de3b02267318a962dfd674c12
data/README.md CHANGED
@@ -3,6 +3,7 @@
3
3
  [![Build Status](https://travis-ci.org/nicoolas25/micro-tracker-mongodb.svg)](https://travis-ci.org/nicoolas25/micro-tracker-mongodb)
4
4
  [![Code Climate](https://codeclimate.com/github/nicoolas25/micro-tracker-mongodb/badges/gpa.svg)](https://codeclimate.com/github/nicoolas25/micro-tracker-mongodb)
5
5
  [![Test Coverage](https://codeclimate.com/github/nicoolas25/micro-tracker-mongodb/badges/coverage.svg)](https://codeclimate.com/github/nicoolas25/micro-tracker-mongodb)
6
+ [![Gem Version](https://badge.fury.io/rb/utracker-mongodb.svg)](http://badge.fury.io/rb/utracker-mongodb)
6
7
 
7
8
  This is a MongoDB backend for the [utracker][utracker] gem.
8
9
 
@@ -0,0 +1,8 @@
1
+ lib = File.expand_path('../lib', __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+
4
+ require 'utracker'
5
+ require 'utracker/mongodb'
6
+
7
+ drawer = Utracker::MongoDB::Drawer.new
8
+ drawer.write_graph("examples/services.dot")
@@ -0,0 +1,13 @@
1
+ digraph message_flow {
2
+ node [style=filled fillcolor=white]
3
+ rankdir=LR
4
+ carl
5
+ carl -> alice
6
+ carl -> bob
7
+ bob
8
+ bob -> carl
9
+ bob -> alice
10
+ alice
11
+ alice -> bob
12
+ alice -> carl
13
+ }
Binary file
@@ -0,0 +1,112 @@
1
+ #
2
+ # In this example 3 bots are sending each other messages. Each bot run in a
3
+ # separated thread. A bot follows this behaviour:
4
+ #
5
+ # 1. Check its inbox (queue)
6
+ # 2. If there is no message in the queue, he sends a message to another bot
7
+ # 3. If there is some message in the queue he reads them one by one
8
+ # 4. For each read message, the robot can send a message to another bot
9
+ # 5. The bot rests
10
+ #
11
+ # For the steps 2, 3 and 4 the bot will log the following events:
12
+ #
13
+ # - seeding
14
+ # - handle
15
+ # - reply
16
+ #
17
+
18
+
19
+ lib = File.expand_path('../lib', __FILE__)
20
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
21
+
22
+ require 'thread'
23
+ require 'utracker'
24
+ require 'utracker/mongodb'
25
+
26
+ BOTS = {
27
+ "alice" => nil,
28
+ "bob" => nil,
29
+ "carl" => nil,
30
+ }
31
+
32
+ class Bot
33
+ attr_accessor :queue
34
+
35
+ def initialize(name)
36
+ @name = name
37
+ @queue = Queue.new
38
+ end
39
+
40
+ def run
41
+ loop do
42
+ consume_queue
43
+ rest
44
+ end
45
+ end
46
+
47
+ def thread
48
+ Thread.current
49
+ end
50
+
51
+ private
52
+
53
+ def consume_queue
54
+ if @queue.empty?
55
+ if target = others.sample
56
+ message = Utracker::Message.pack("I have nothing to do...")
57
+ target.queue.push(message.to_json)
58
+ message.log("seeding")
59
+ end
60
+ else
61
+ until @queue.empty?
62
+ serialization = @queue.pop
63
+ handle(serialization)
64
+ end
65
+ end
66
+ end
67
+
68
+ def handle(serialization)
69
+ message = Utracker::Message.unpack(serialization)
70
+ message.log("handle", hide_payload: true)
71
+ reply_to(message)
72
+ end
73
+
74
+ def reply_to(message)
75
+ if rand(2) == 0 && (target = others.sample)
76
+ reply = message.pack("Unleash the kraken!")
77
+ target.queue.push(reply.to_json)
78
+ reply.log("reply")
79
+ end
80
+ end
81
+
82
+ def others
83
+ BOTS.each_with_object([]) do |(name, bot), list|
84
+ list << bot if bot && name != @name
85
+ end
86
+ end
87
+
88
+ def rest
89
+ sleep rand
90
+ end
91
+
92
+ end
93
+
94
+ threads = BOTS.keys.map do |name|
95
+ Thread.new do
96
+ Utracker.configure do |config|
97
+ config[:service_name] = name
98
+ config[:logger_class] = Utracker::MongoDB::Logger
99
+ end
100
+
101
+ Bot.new(name).tap do |bot|
102
+ BOTS[name] = bot
103
+ bot.run
104
+ end
105
+ end
106
+ end
107
+
108
+ begin
109
+ threads.each(&:join)
110
+ rescue Interrupt
111
+ threads.each(&:terminate)
112
+ end
@@ -1,5 +1,6 @@
1
1
  module Utracker
2
2
  module MongoDB
3
+ autoload :Drawer, 'utracker/mongodb/drawer'
3
4
  autoload :Logger, 'utracker/mongodb/logger'
4
5
  end
5
6
  end
@@ -0,0 +1,104 @@
1
+ require 'mongo'
2
+
3
+ class Utracker::MongoDB::Drawer < Utracker::Drawer
4
+ attr_reader :database
5
+
6
+ def initialize(database_name: "utracker", collection_name: "entries")
7
+ @client = Mongo::MongoClient.new
8
+ @database = @client[database_name]
9
+ @collection_name = collection_name
10
+ end
11
+
12
+ protected
13
+
14
+ def build_graph
15
+ nodes.values.each do |node|
16
+ node.edges = edges_for(node)
17
+ end
18
+ end
19
+
20
+ private
21
+
22
+ def nodes
23
+ @nodes ||= service_names.each_with_object({}) do |service_name, directory|
24
+ directory[service_name] = Utracker::Drawer::Node.new(service_name, nil)
25
+ end
26
+ end
27
+
28
+ def service_names
29
+ collection.distinct('service')
30
+ end
31
+
32
+ def edges_for(node)
33
+ aggregate = edges.find { |agg| agg["_id"]["service"] == node.service }
34
+ aggregate && aggregate["edges"].map{ |service_name| nodes[service_name] }
35
+ end
36
+
37
+ def edges
38
+ @edges ||= edge_collection.aggregate([
39
+ { "$unwind" => "$value.handled_by" },
40
+ { "$group" => {
41
+ "_id" => { "service" => "$value.authored_by" },
42
+ "edges" => { "$addToSet" => "$value.handled_by" },
43
+ },
44
+ },
45
+ ])
46
+ end
47
+
48
+ def edge_collection
49
+ @edge_collection ||= collection.map_reduce(
50
+ EDGE_MAP_FN,
51
+ EDGE_REDUCE_FN,
52
+ out: { replace: "#{@collection_name}_drawer" }
53
+ )
54
+ end
55
+
56
+ def collection
57
+ @collection ||= database[@collection_name]
58
+ end
59
+
60
+ EDGE_MAP_FN = <<-MAP
61
+ function() {
62
+ var value = { authored_by: this.service, handled_by: [], handled_at: {} };
63
+ value.handled_at[this.service] = this.datetime;
64
+ var key = this.uuid;
65
+ emit(key, value);
66
+ }
67
+ MAP
68
+
69
+ EDGE_REDUCE_FN = <<-REDUCE
70
+ function(key, values) {
71
+ var handled_at = {};
72
+ var handled_by = [];
73
+ var first_handled = new Date();
74
+ var first_handler;
75
+
76
+ values.forEach(function(value) {
77
+ var author = value.authored_by;
78
+ var datetime = value.handled_at[author];
79
+
80
+ if (datetime < first_handled) {
81
+ first_handler = author;
82
+ first_handled = datetime;
83
+ }
84
+
85
+ if (!(author in handled_at) || datetime < handled_at[author]) {
86
+ handled_at[author] = datetime;
87
+ }
88
+ });
89
+
90
+ for(var service in handled_at) {
91
+ if (service !== first_handler) {
92
+ handled_by.push(service);
93
+ }
94
+ }
95
+
96
+ return {
97
+ authored_by: first_handler,
98
+ handled_by: handled_by,
99
+ handled_at: handled_at
100
+ };
101
+ }
102
+ REDUCE
103
+
104
+ end
@@ -1,34 +1,29 @@
1
1
  require 'mongo'
2
2
 
3
- module Utracker
4
- module MongoDB
5
- class Logger < Utracker::Logger
6
- attr_reader :client
7
- attr_reader :database
3
+ class Utracker::MongoDB::Logger < Utracker::Logger
4
+ attr_reader :client, :database, :collection_name
8
5
 
9
- def initialize(database_name: "utracker", collection_name: "entries")
10
- @client = Mongo::MongoClient.new
11
- @database = @client[database_name]
12
- @collection_name = collection_name
13
- end
14
-
15
- protected
6
+ def initialize(database_name: "utracker", collection_name: "entries")
7
+ @client = Mongo::MongoClient.new
8
+ @database = @client[database_name]
9
+ @collection_name = collection_name
10
+ end
16
11
 
17
- def write(event)
18
- event_collection << {
19
- datetime: event.datetime,
20
- service: event.service,
21
- description: event.description,
22
- uuid: event.message.uuid,
23
- parent_uuid: event.message.parent_uuid,
24
- payload: event.payload,
25
- }
26
- end
12
+ protected
27
13
 
28
- def event_collection
29
- @event_collection ||= database[@collection_name]
30
- end
14
+ def write(event)
15
+ collection << {
16
+ datetime: event.datetime,
17
+ service: event.service,
18
+ description: event.description,
19
+ uuid: event.message.uuid,
20
+ parent_uuid: event.message.parent_uuid,
21
+ payload: event.payload,
22
+ }
23
+ end
31
24
 
32
- end
25
+ def collection
26
+ @collection ||= database[@collection_name]
33
27
  end
28
+
34
29
  end
@@ -1,5 +1,5 @@
1
1
  module Utracker
2
2
  module MongoDB
3
- VERSION = "0.0.1"
3
+ VERSION = "0.0.2"
4
4
  end
5
5
  end
@@ -0,0 +1,46 @@
1
+ RSpec.describe Utracker::MongoDB::Drawer do
2
+ let(:instance) { described_class.new(database_name: database_name,
3
+ collection_name: collection_name) }
4
+
5
+ let(:database_name) { "utracker_test" }
6
+ let(:collection_name) { "entries" }
7
+
8
+ before { instance.database.drop_collection(collection_name) }
9
+
10
+ describe "#build_graph" do
11
+ subject { instance.__send__(:build_graph) }
12
+ it { is_expected.to eq [] }
13
+
14
+ context "after writing event via the logger" do
15
+ let(:logger) { Utracker::MongoDB::Logger.new(database_name: database_name,
16
+ collection_name: collection_name) }
17
+
18
+ let(:graph) do
19
+ node1 = Utracker::Drawer::Node.new("node1", [])
20
+ node2 = Utracker::Drawer::Node.new("node2", nil)
21
+ node1.edges << node1
22
+ [node1, node2]
23
+ end
24
+
25
+ before do
26
+ node1_event = {
27
+ datetime: Time.now,
28
+ service: "node1",
29
+ description: "sending",
30
+ message: double(parent_uuid: nil, uuid: '1'),
31
+ payload: "payload",
32
+ options: {},
33
+ }
34
+ node2_event = node1_event.merge({
35
+ datetime: Time.now,
36
+ service: "node2",
37
+ description: "receiving",
38
+ })
39
+ logger.__send__(:write, double("Event", node1_event))
40
+ logger.__send__(:write, double("Event", node2_event))
41
+ end
42
+
43
+ it { is_expected.to eq graph }
44
+ end
45
+ end
46
+ end
@@ -17,7 +17,7 @@ Gem::Specification.new do |spec|
17
17
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
18
  spec.require_paths = ["lib"]
19
19
 
20
- spec.add_dependency "utracker"
20
+ spec.add_dependency "utracker", "~> 0.0.2"
21
21
  spec.add_dependency "bson_ext"
22
22
  spec.add_dependency "mongo"
23
23
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: utracker-mongodb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nicolas ZERMATI
@@ -14,16 +14,16 @@ dependencies:
14
14
  name: utracker
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ">="
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '0'
19
+ version: 0.0.2
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ">="
24
+ - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '0'
26
+ version: 0.0.2
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: bson_ext
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -151,10 +151,16 @@ files:
151
151
  - LICENSE.txt
152
152
  - README.md
153
153
  - Rakefile
154
+ - examples/draw_services.rb
155
+ - examples/services.dot
156
+ - examples/services.dot.png
157
+ - examples/services.rb
154
158
  - lib/utracker/mongodb.rb
159
+ - lib/utracker/mongodb/drawer.rb
155
160
  - lib/utracker/mongodb/logger.rb
156
161
  - lib/utracker/mongodb/version.rb
157
162
  - spec/spec_helper.rb
163
+ - spec/utracker/mongodb/drawer_spec.rb
158
164
  - spec/utracker/mongodb/logger_spec.rb
159
165
  - utracker-mongodb.gemspec
160
166
  homepage: http://github.com/nicoolas25/micro-tracker-mongodb
@@ -183,4 +189,5 @@ specification_version: 4
183
189
  summary: MongoDB backend for utracker.
184
190
  test_files:
185
191
  - spec/spec_helper.rb
192
+ - spec/utracker/mongodb/drawer_spec.rb
186
193
  - spec/utracker/mongodb/logger_spec.rb