vayacondios-server 0.2.11 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (142) hide show
  1. data/.gitignore +3 -1
  2. data/.travis.yml +2 -0
  3. data/Gemfile +15 -9
  4. data/LICENSE.md +2 -6
  5. data/Procfile +1 -1
  6. data/README.md +656 -111
  7. data/Rakefile +89 -6
  8. data/bin/vcd +10 -0
  9. data/bin/vcd-server +8 -0
  10. data/config/database.yml +6 -0
  11. data/config/spec.example.yml +18 -0
  12. data/config/vayacondios.example.yml +15 -0
  13. data/config/vcd-server.rb +37 -0
  14. data/examples/configuration.rb +56 -0
  15. data/examples/event_stream.rb +19 -0
  16. data/examples/simple.rb +61 -0
  17. data/features/event.feature +319 -0
  18. data/features/events.feature +208 -0
  19. data/features/stash.feature +840 -0
  20. data/features/stashes.feature +492 -0
  21. data/features/step_definitions/stash_steps.rb +113 -0
  22. data/features/stream.feature +30 -0
  23. data/features/support/em.rb +14 -0
  24. data/features/support/env.rb +13 -0
  25. data/lib/vayacondios/configuration.rb +63 -0
  26. data/lib/vayacondios/server/api.rb +126 -0
  27. data/lib/vayacondios/server/api_options.rb +56 -0
  28. data/lib/vayacondios/server/configuration.rb +23 -0
  29. data/lib/vayacondios/server/driver.rb +71 -0
  30. data/lib/vayacondios/server/drivers/mongo.rb +126 -0
  31. data/lib/vayacondios/server/handlers/document_handler.rb +81 -0
  32. data/lib/vayacondios/server/handlers/event_handler.rb +31 -26
  33. data/lib/vayacondios/server/handlers/events_handler.rb +31 -0
  34. data/lib/vayacondios/server/handlers/stash_handler.rb +69 -0
  35. data/lib/vayacondios/server/handlers/stashes_handler.rb +49 -0
  36. data/lib/vayacondios/server/handlers/stream_handler.rb +39 -0
  37. data/lib/vayacondios/server/models/document.rb +87 -0
  38. data/lib/vayacondios/server/models/event.rb +198 -0
  39. data/lib/vayacondios/server/models/stash.rb +100 -0
  40. data/lib/vayacondios/server.rb +35 -0
  41. data/lib/vayacondios-server.rb +19 -13
  42. data/lib/vayacondios.rb +22 -0
  43. data/pom.xml +124 -4
  44. data/spec/configuration_spec.rb +41 -0
  45. data/spec/server/api_options_spec.rb +32 -0
  46. data/spec/server/api_spec.rb +279 -0
  47. data/spec/server/configuration_spec.rb +27 -0
  48. data/spec/server/drivers/mongo_spec.rb +107 -0
  49. data/spec/server/handlers/event_handler_spec.rb +62 -0
  50. data/spec/server/handlers/events_handler_spec.rb +51 -0
  51. data/spec/server/handlers/stash_handler_spec.rb +68 -0
  52. data/spec/server/handlers/stashes_handler_spec.rb +50 -0
  53. data/spec/server/handlers/stream_handler_spec.rb +5 -0
  54. data/spec/server/models/document_spec.rb +9 -0
  55. data/spec/server/models/event_spec.rb +185 -0
  56. data/spec/server/models/stash_spec.rb +95 -0
  57. data/spec/spec_helper.rb +23 -3
  58. data/spec/support/database_helper.rb +42 -0
  59. data/spec/support/log_helper.rb +19 -0
  60. data/spec/support/shared_context_for_events.rb +22 -0
  61. data/spec/support/shared_context_for_stashes.rb +24 -0
  62. data/spec/support/shared_examples_for_handlers.rb +32 -0
  63. data/src/main/java/com/infochimps/vayacondios/BaseClient.java +342 -0
  64. data/src/main/java/com/infochimps/vayacondios/HTTPClient.java +426 -0
  65. data/src/main/java/com/infochimps/vayacondios/VayacondiosClient.java +487 -65
  66. data/src/main/java/com/infochimps/vayacondios/test/IntegrationTest.java +3 -0
  67. data/src/test/java/com/infochimps/vayacondios/BaseClientTest.java +50 -0
  68. data/src/test/java/com/infochimps/vayacondios/HTTPClientIT.java +267 -0
  69. data/vayacondios-server.gemspec +9 -9
  70. metadata +127 -122
  71. checksums.yaml +0 -15
  72. data/.rspec +0 -2
  73. data/.yardopts +0 -10
  74. data/Guardfile +0 -41
  75. data/app/http_shim.rb +0 -71
  76. data/bin/vcd.sh +0 -27
  77. data/config/http_shim.rb +0 -43
  78. data/config/vayacondios.example.yaml +0 -7
  79. data/config/vayacondios.yaml +0 -7
  80. data/examples/java/ItemSetTest.java +0 -76
  81. data/lib/tasks/publish.rake +0 -23
  82. data/lib/tasks/spec.rake +0 -11
  83. data/lib/tasks/yard.rake +0 -2
  84. data/lib/vayacondios/client/config.rb +0 -7
  85. data/lib/vayacondios/client/configliere.rb +0 -38
  86. data/lib/vayacondios/client/cube_client.rb +0 -39
  87. data/lib/vayacondios/client/http_client.rb +0 -49
  88. data/lib/vayacondios/client/itemset.rb +0 -130
  89. data/lib/vayacondios/client/legacy_switch.rb +0 -43
  90. data/lib/vayacondios/client/notifier.rb +0 -123
  91. data/lib/vayacondios/client/zabbix_client.rb +0 -148
  92. data/lib/vayacondios/legacy_switch.rb +0 -43
  93. data/lib/vayacondios/server/errors/bad_request.rb +0 -6
  94. data/lib/vayacondios/server/errors/not_found.rb +0 -6
  95. data/lib/vayacondios/server/handlers/config_handler.rb +0 -32
  96. data/lib/vayacondios/server/handlers/itemset_handler.rb +0 -60
  97. data/lib/vayacondios/server/legacy_switch.rb +0 -43
  98. data/lib/vayacondios/server/model/config_document.rb +0 -89
  99. data/lib/vayacondios/server/model/document.rb +0 -25
  100. data/lib/vayacondios/server/model/event_document.rb +0 -94
  101. data/lib/vayacondios/server/model/itemset_document.rb +0 -126
  102. data/lib/vayacondios/server/rack/extract_methods.rb +0 -35
  103. data/lib/vayacondios/server/rack/jsonize.rb +0 -43
  104. data/lib/vayacondios/server/rack/params.rb +0 -50
  105. data/lib/vayacondios/server/rack/path.rb +0 -23
  106. data/lib/vayacondios/server/rack/path_validation.rb +0 -22
  107. data/lib/vayacondios/version.rb +0 -3
  108. data/lib/vayacondios-client.rb +0 -22
  109. data/scripts/hadoop_monitor/configurable.rb +0 -66
  110. data/scripts/hadoop_monitor/hadoop_attempt_scraper.rb +0 -45
  111. data/scripts/hadoop_monitor/hadoop_client.rb +0 -273
  112. data/scripts/hadoop_monitor/hadoop_monitor.rb +0 -101
  113. data/scripts/hadoop_monitor/hadoopable.rb +0 -65
  114. data/scripts/hadoop_monitor/machine_monitor.rb +0 -115
  115. data/scripts/s3_cataloger/buckets +0 -33
  116. data/scripts/s3_cataloger/foreach_bucket +0 -88
  117. data/scripts/s3_cataloger/parse_ls.py +0 -391
  118. data/spec/client/itemset_legacy_spec.rb +0 -55
  119. data/spec/client/itemset_spec.rb +0 -60
  120. data/spec/client/notifier_spec.rb +0 -120
  121. data/spec/server/config_spec.rb +0 -113
  122. data/spec/server/event_spec.rb +0 -103
  123. data/spec/server/itemset_legacy_spec.rb +0 -320
  124. data/spec/server/itemset_spec.rb +0 -317
  125. data/spec/server/rack/extract_methods_spec.rb +0 -60
  126. data/spec/server/rack/path_spec.rb +0 -36
  127. data/spec/server/rack/path_validation_spec.rb +0 -22
  128. data/spec/server/server_spec.rb +0 -20
  129. data/spec/support/mongo_cleaner.rb +0 -32
  130. data/src/main/java/ItemSetTest.java +0 -76
  131. data/src/main/java/com/infochimps/util/CurrentClass.java +0 -26
  132. data/src/main/java/com/infochimps/util/DebugUtil.java +0 -38
  133. data/src/main/java/com/infochimps/util/HttpHelper.java +0 -181
  134. data/src/main/java/com/infochimps/vayacondios/ItemSets.java +0 -373
  135. data/src/main/java/com/infochimps/vayacondios/LinkToVCD.java +0 -18
  136. data/src/main/java/com/infochimps/vayacondios/MemoryVCDShim.java +0 -84
  137. data/src/main/java/com/infochimps/vayacondios/Organization.java +0 -62
  138. data/src/main/java/com/infochimps/vayacondios/PathBuilder.java +0 -13
  139. data/src/main/java/com/infochimps/vayacondios/StandardVCDLink.java +0 -218
  140. data/src/main/java/com/infochimps/vayacondios/VCDIntegrationTest.java +0 -108
  141. data/src/test/java/com/infochimps/vayacondios/TestVayacondiosInMemory.java +0 -78
  142. data/vayacondios-client.gemspec +0 -25
@@ -0,0 +1,69 @@
1
+ module Vayacondios::Server
2
+ class StashHandler < DocumentHandler
3
+
4
+ # Create a stash.
5
+ #
6
+ # @param [Hash] params routing information like `organization`, `topic,`, or `id`
7
+ # @param [Hash] document the body of the stash
8
+ def create(params, document)
9
+ stash = Stash.create(params, document) do |request|
10
+ database.call(:insert, request)
11
+ end
12
+ stash.delete(:topic)
13
+ stash
14
+ end
15
+
16
+ # Find and show a particular stash.
17
+ #
18
+ # @param [Hash] params routing information like `organization`, `topic,`, or `id`
19
+ # @raise [Goliath::Validation::Error] if no stash is found. Returns a 404.
20
+ def retrieve(params, document)
21
+ stash = Stash.find(params) do |request|
22
+ database.call(:retrieve, request)
23
+ end or raise Goliath::Validation::NotFoundError.new("Stash with topic <#{params[:topic]}> not found")
24
+ stash.delete(:topic)
25
+ if slice = params[:id]
26
+ stash[slice.to_sym] or raise Goliath::Validation::NotFoundError.new("Stash with topic <#{params[:topic]}> found, but does not contain Id <#{slice}>")
27
+ else
28
+ stash
29
+ end
30
+ end
31
+
32
+ # Update a stash.
33
+ #
34
+ # @param [Hash] params routing information like `organization`, `topic,`, or `id`
35
+ # @param [Hash] document the body of the stash
36
+ # def update(params, document)
37
+ # id = params.delete(:id)
38
+ # raise Goliath::Validation::BadRequestError.new("If not including an id the document must be a Hash") if id.blank? && !document.is_a?(Hash)
39
+ # # Not sure if I like this behavior for updating a non-existant document
40
+ # original = begin ; retrieve(params.dup, nil) ; rescue Goliath::Validation::NotFoundError ; nil ; end
41
+ # if original.is_a? Hash
42
+ # if id
43
+ # original.delete(id.to_sym)
44
+ # original.merge!(id => document) unless document.nil?
45
+ # else
46
+ # original.merge! document
47
+ # end
48
+ # else
49
+ # params[:id] = id if id && document
50
+ # original = document
51
+ # end
52
+ # Stash.update(params, original) do |request|
53
+ # database.call(:update, request)
54
+ # end
55
+ # end
56
+
57
+ # Delete a single stash.
58
+ #
59
+ # @param [Hash] params routing information like `organization`, `topic,`, or `id`
60
+ # @param [Hash] document presentation or filter information
61
+ def delete(params, document)
62
+ raise Goliath::Validation::NotImplementedError.new 'Deleting an Id from a Stash is not supported' if params[:id]
63
+ Stash.destroy(params, {}) do |request, options|
64
+ database.call(:remove, request, options)
65
+ end
66
+ action_successful
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,49 @@
1
+ module Vayacondios::Server
2
+ class StashesHandler < DocumentHandler
3
+
4
+ # Apply a replacement across many stashes.
5
+ #
6
+ # @param [Hash] params routing information like `organization`, `topic,`, or `id`
7
+ # @param [Hash] document the body of the request containing a search query and a replacement
8
+ # def create(params, document)
9
+ # document.symbolize_keys!
10
+ # query = document[:query] || {}
11
+ # replacement = document[:update] || {}
12
+ # Stash.replace_many(params, query, replacement)
13
+ # end
14
+
15
+ # Search for stashes matching a given query.
16
+ #
17
+ # @param [Hash] params routing information like `organization`, `topic,`, or `id`
18
+ # @param [Hash] query a search query
19
+ def retrieve(params, query)
20
+ stashes = Stash.search(params, query) do |request, filter, options|
21
+ database.call(:search, request, filter, options)
22
+ end
23
+ end
24
+
25
+ # Apply an update across many stashes.
26
+ #
27
+ # @param [Hash] params routing information like `organization`, `topic,`, or `id`
28
+ # @param [Hash] document the body of the request containing a search query and an update
29
+ # def update(params={}, document={})
30
+ # query = (document[:query] || document['query'] || {})
31
+ # update = (document[:update] || document['update'] || {})
32
+ # Stash.update_many(log, database, params, query, update)
33
+ # end
34
+
35
+ # Delete many stashes that match a query.
36
+ #
37
+ # @param [Hash] params routing information like `organization`, `topic,`, or `id`
38
+ # @param [Hash] query a search query
39
+ # @param [Hash] document the body of the request containing a search query and an update
40
+ def delete(params, query)
41
+ raise Goliath::Validation::BadRequestError.new 'Query cannot be empty' if query.empty?
42
+ Stash.destroy(params, query) do |request, filter|
43
+ database.call(:remove, request, filter)
44
+ end
45
+ action_successful
46
+ end
47
+
48
+ end
49
+ end
@@ -0,0 +1,39 @@
1
+ module Vayacondios::Server
2
+ class StreamHandler < EventsHandler
3
+
4
+ attr_reader :cursor, :timer, :on_data
5
+
6
+ def retrieve(params, query)
7
+ @timer = EM::Synchrony.add_periodic_timer(1){ stream_events }
8
+ @cursor = Event.receive(params).prepare_search(query)
9
+ Goliath::Response::STREAMING
10
+ end
11
+
12
+ def stream_data(&on_data)
13
+ @on_data = on_data
14
+ self
15
+ end
16
+
17
+ def close_stream!
18
+ timer.cancel
19
+ end
20
+
21
+ def update_cursor latest
22
+ cursor.filter.delete(:_t)
23
+ cursor.prepare_search(after: latest)
24
+ end
25
+
26
+ def stream_events
27
+ log.debug 'Streaming events'
28
+ log.debug " Stream cursor is #{cursor.filter}"
29
+ available = database.call(:search, cursor, cursor.filter.dup, {})
30
+ unless available.empty?
31
+ available.each do |result|
32
+ event = Event.new.format_response(result)
33
+ on_data.call event
34
+ update_cursor event[:time]
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,87 @@
1
+ # The Document model is a base model used by Event, Stash, &c.
2
+ #
3
+ # The `organization` and `topic` properties are defined as instance
4
+ # attributes because they are used for routing the document.
5
+ # Subclasses should continue to store each separate piece of routing
6
+ # information as its own instance variable and store the entire
7
+ # payload/data as a single field.
8
+ #
9
+ # organization coca_cola
10
+ # |---- topic |---- ad_campaigns
11
+ # |---- ... ------> |---- web_traffic
12
+ # `---- topic `---- social_media_buzz
13
+ #
14
+ # @attr [String] organization the organization this document belongs to
15
+ # @attr [String] topic the unit which identifies documents of a given "kind"
16
+ module Vayacondios::Server
17
+ class Document
18
+ include Gorillib::Model
19
+
20
+ field :organization, String
21
+ field :topic, String
22
+ field :id, String
23
+ field :body, Hash
24
+ field :filter, Hash
25
+
26
+ def receive_organization name
27
+ @organization = sanitize_location_name(name).gsub(/^system\./, '_system.')
28
+ end
29
+
30
+ def format_response result
31
+ from_document(result.symbolize_keys.compact).external_document
32
+ end
33
+
34
+ # A class for errors that arise within documents due to internal or
35
+ # IO errors.
36
+ Error = Class.new(StandardError)
37
+
38
+ # Sanitize a string to make a suitable component of a database
39
+ # location name.
40
+ #
41
+ # Replaces all characters that aren't letters, digits, underscores,
42
+ # periods, or hyphens with underscores. Also replaces periods at
43
+ # the beginning or at the end of a collection name with an
44
+ # underscore.
45
+ #
46
+ # @param [String] name
47
+ # @return [String] the sanitized `name`
48
+ def sanitize_location_name name
49
+ name.to_s.gsub(/^\.|[^-\w\.]+|\.$/, '_')
50
+ end
51
+
52
+ class << self
53
+ def extract_query_options! params
54
+ params.symbolize_keys!
55
+ opts = {}
56
+ [:limit, :order, :sort, :fields].each{ |opt| opts[opt] = params.delete opt }
57
+ opts.merge default_query_options
58
+ end
59
+
60
+ def search(params, query, &driver)
61
+ options = extract_query_options! query
62
+ action = receive(params).prepare_search(query)
63
+ result = driver.call(action, action.filter, options)
64
+ result.map{ |res| new.format_response res }
65
+ end
66
+
67
+ def create(params, document, &driver)
68
+ action = receive(params).prepare_create(document)
69
+ result = driver.call(action)
70
+ action.format_response result
71
+ end
72
+
73
+ def find(params, &driver)
74
+ action = receive(params).prepare_find
75
+ result = driver.call(action, {})
76
+ return nil if result.nil?
77
+ action.format_response result
78
+ end
79
+
80
+ def destroy(params, document, &driver)
81
+ action = receive(params).prepare_destroy(document.symbolize_keys)
82
+ result = driver.call(action, action.filter)
83
+ return result
84
+ end
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,198 @@
1
+ # Events are documents with arbitrary key/value data but which also
2
+ # have
3
+ #
4
+ # * an ID, auto-generated to a random unique value when none is provided
5
+ # * a timestamp, auto-generated to the current time when none is provided
6
+ #
7
+ # An HTTP request which announces a new event
8
+ #
9
+ # ```
10
+ # POST /v2/coca_cola/event/ad_campaigns
11
+ # { "impresions": 23829, "errors": 29 }
12
+ # ```
13
+ #
14
+ # would result in a document in the `coca_cola.ad_campaigns.events`
15
+ # collection with the following structure:
16
+ #
17
+ # ```
18
+ # {
19
+ # "_id": ObjectId("51c38ad981bdb34d32000001"),
20
+ # "t": ISODate("2013-06-20T23:06:01.846Z"),
21
+ # "d": {
22
+ # "impressions": 23829,
23
+ # "errors": 29
24
+ # }
25
+ # }
26
+ # ```
27
+ #
28
+ # When explictly setting the ID and timestamp with a request like:
29
+ #
30
+ # ```
31
+ # POST /v2/coca_cola/event/ad_campaigns/atx-jan-01
32
+ # { "impresions": 23829, "errors": 29, "time": "2013-01-20 18:09:39 -0500" }
33
+ # ```
34
+ #
35
+ # a document would still be generated in the
36
+ # `coca_cola.ad_campaigns.events` collection with a similar structure:
37
+ #
38
+ # ```
39
+ # {
40
+ # "_id": "atx-jan-01",
41
+ # "t": ISODate("2013-01-20T23:09:39Z")
42
+ # "d": {
43
+ # "impressions": 23829,
44
+ # "errors": 29
45
+ # }
46
+ # }
47
+ # ```
48
+ #
49
+ # @attr [Time] timestamp the timestamp for which this event records data
50
+ #
51
+ module Vayacondios::Server
52
+ class Event < Vayacondios::Server::Document
53
+
54
+ # The default number of events returned when searching.
55
+ LIMIT = 50
56
+
57
+ # The default sort order when searching
58
+ ORDER = 'descending'
59
+
60
+ # The default sort field when searching.
61
+ SORT = 'time'
62
+
63
+ # The default time window (measured relative to the current time)
64
+ # when searching.
65
+ WINDOW = 3600
66
+
67
+ def self.default_query_options
68
+ { limit: LIMIT, order: ORDER, sort: SORT }
69
+ end
70
+
71
+ field :time, Time # assigned or Time.now.utc
72
+ field :host, String # assigned or read from the client
73
+
74
+ # Set the topic of this document, sanitizing it for the database
75
+ #
76
+ # @param [String] name
77
+ # @return [String] the sanitized `name`
78
+ def receive_topic name
79
+ @topic = sanitize_location_name name
80
+ end
81
+
82
+ # Normalizes the time
83
+ def receive_time t
84
+ @time = format_time to_timestamp(t)
85
+ end
86
+
87
+ # Parses an object into a timestamp.
88
+ #
89
+ # @param [String, Numeric, Time, nil] obj
90
+ # @param [Time] default the time value to return if none could be found in the `obj`
91
+ # @return [Time]
92
+ def to_timestamp(obj, default = Time.now)
93
+ case obj
94
+ when String then Time.parse(obj)
95
+ when Date then obj.to_time
96
+ when Time then obj
97
+ when Numeric then Time.at(obj)
98
+ else default
99
+ end
100
+ rescue ArgumentError => e
101
+ default
102
+ end
103
+
104
+ def format_time ts
105
+ ts.round(3).utc
106
+ end
107
+
108
+ # The name of the collection this event will store its data in.
109
+ #
110
+ # @return [String]
111
+ def location
112
+ [organization, topic, 'events'].join('.')
113
+ end
114
+
115
+ # An events internal database representation
116
+ def document
117
+ { _id: id, _t: time, _d: body }.compact
118
+ end
119
+
120
+ # Populate a new Event from a database representation
121
+ def from_document doc
122
+ d = {}.tap do |d|
123
+ d[:id] = doc[:_id]
124
+ d[:time] = doc[:_t]
125
+ d[:body] = doc[:_d]
126
+ end.compact
127
+ receive! d
128
+ self
129
+ end
130
+
131
+ # An event as presented to a user
132
+ def external_document
133
+ { id: id, time: time.iso8601(3) }.merge(body)
134
+ end
135
+
136
+ # Returns a Hash that can be used for selection criteria in a query
137
+ # to a MongoDB collection.
138
+ #
139
+ # For any given `query` object, this method should be run **after**
140
+ # Event.projector because Event.projector modifies the `query` by
141
+ # removing certain special options which would otherwise be
142
+ # interpreted by this method..
143
+ #
144
+ # @param [Hash] query
145
+ # @option query [String, Numeric, Time, nil] from the earliest time for a matched event (>=)
146
+ # @option query [String, Numeric, Time, nil] upto the latest time for a matched event (<=)
147
+ # @option query [String, Numeric, Time, nil] after the earliest time for a matched event (>)
148
+ # @option query [String, Numeric, Time, nil] before the latest time for a matched event (<)
149
+ # @option query [String, Regexp]] id a regular expression that matches the ID of the event
150
+ # @return [Hash] the selector Hash
151
+ # @see Event.projector
152
+ def event_filter query
153
+ filter = { _t: {} }.tap do |filter|
154
+ if query.has_key? :after
155
+ filter[:_t][:gt] = to_timestamp query.delete(:after)
156
+ query.delete(:from)
157
+ elsif query.has_key? :from
158
+ filter[:_t][:gte] = to_timestamp query.delete(:from)
159
+ end
160
+
161
+ if query.has_key? :before
162
+ filter[:_t][:lt] = to_timestamp query.delete(:before)
163
+ query.delete(:upto)
164
+ elsif query.has_key? :upto
165
+ filter[:_t][:lte] = to_timestamp query.delete(:upto)
166
+ end
167
+ # sel['_id'] = Regexp.new(query.delete(:id)) if query[:id]
168
+ query.each_pair{ |key, val| filter[:_d] ||= {} ; filter[:_d][key] = val }
169
+ end
170
+ end
171
+
172
+ # Prepare Event search request
173
+ def prepare_search query
174
+ receive!(filter: event_filter(query))
175
+ self
176
+ end
177
+
178
+ # Prepare Event retrieve request
179
+ def prepare_find
180
+ raise Error.new('Cannot find an event without an ID') if id.blank?
181
+ self
182
+ end
183
+
184
+ # Prepare Event create request
185
+ def prepare_create document
186
+ raise Error.new('Events must be Hash-like to create') unless document.is_a?(Hash)
187
+ document.symbolize_keys!
188
+ receive!(time: document.delete(:time), body: document)
189
+ self
190
+ end
191
+
192
+ # Prepare Event remove request
193
+ def prepare_destroy query
194
+ receive!(filter: event_filter(query))
195
+ self
196
+ end
197
+ end
198
+ end
@@ -0,0 +1,100 @@
1
+ # Stashes are documents with arbitrary key/value data.
2
+ #
3
+ # An HTTP request which sets a new stash
4
+ #
5
+ # ```
6
+ # POST /v2/coca_cola/stash/campaigns
7
+ # { "creatives": [ "atx-jan-01", "bos-jan-01"], "test": false }
8
+ # ```
9
+ #
10
+ # would result in a document in the `coca_cola.stash` collection with
11
+ # the following structure:
12
+ #
13
+ # ```
14
+ # {
15
+ # "_id": "campaigns",
16
+ # "creatives": [ "atx-jan-01", "bos-jan-01"],
17
+ # "test": false
18
+ # }
19
+ # ```
20
+ #
21
+ module Vayacondios::Server
22
+ class Stash < Vayacondios::Server::Document
23
+
24
+ # The default number of stashes returned when searching.
25
+ LIMIT = 50
26
+
27
+ # The default sort order when searching.
28
+ SORT = 'ascending'
29
+ ORDER = '_id'
30
+
31
+ # Returned as an acknowledgement of the request when there is no
32
+ # better option (#destroy, #update_many, &c.)
33
+ # OK = {ok: true}
34
+
35
+ def self.default_query_options
36
+ { limit: LIMIT, order: ORDER, sort: SORT }
37
+ end
38
+
39
+ # The name of the collection this stash will store its data in.
40
+ #
41
+ # @return [String]
42
+ def location
43
+ [organization.to_s, 'stash'].join('.')
44
+ end
45
+
46
+ def document
47
+ { _id: topic }.compact.merge(body || {})
48
+ end
49
+
50
+ def from_document doc
51
+ d = {}.tap do |d|
52
+ d[:topic] = doc.delete(:_id)
53
+ doc = nil if doc.empty?
54
+ if body.nil?
55
+ new_body = doc
56
+ else
57
+ new_body = body.merge(doc || {})
58
+ end
59
+ d[:body] = new_body
60
+ end
61
+ receive! d
62
+ self
63
+ end
64
+
65
+ def external_document
66
+ { topic: topic }.merge(body || {})
67
+ end
68
+
69
+ def prepare_search query
70
+ filter = query.merge(_id: topic).compact
71
+ receive!(filter: filter)
72
+ self
73
+ end
74
+
75
+ def prepare_create document
76
+ if document.is_a? Hash
77
+ document.symbolize_keys!
78
+ raise Error.new ':topic is a reserved key and cannot be used in a stash document' if document.has_key?(:topic)
79
+ end
80
+ if id.blank?
81
+ raise Error.new 'If not including an Id, the document must be a Hash' unless document.is_a? Hash
82
+ receive!(body: document)
83
+ else
84
+ receive!(body: { id => document })
85
+ end
86
+ self
87
+ end
88
+
89
+ def prepare_find
90
+ raise Error.new('Cannot find a stash without a topic') unless topic
91
+ self
92
+ end
93
+
94
+ def prepare_destroy query
95
+ filter = query.merge(_id: topic).compact
96
+ receive!(filter: filter)
97
+ self
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,35 @@
1
+ require 'goliath'
2
+ require 'goliath/chimp'
3
+ require 'em-mongo'
4
+ require 'em-synchrony/em-http'
5
+ require 'em-synchrony/em-mongo'
6
+ require 'configliere'
7
+
8
+ require 'gorillib/object/blank'
9
+ require 'gorillib/enumerable/sum'
10
+ require 'gorillib/hash/compact'
11
+ require 'gorillib/hash/deep_merge'
12
+ require 'gorillib/hash/keys'
13
+ require 'gorillib/model'
14
+ require 'gorillib/string/constantize'
15
+ require 'gorillib/string/inflections'
16
+ require 'multi_json'
17
+
18
+ require 'vayacondios'
19
+ require 'vayacondios/configuration'
20
+
21
+ require 'vayacondios/server/api_options'
22
+ require 'vayacondios/server/configuration'
23
+ require 'vayacondios/server/driver'
24
+ require 'vayacondios/server/drivers/mongo'
25
+
26
+ require 'vayacondios/server/models/document'
27
+ require 'vayacondios/server/models/event'
28
+ require 'vayacondios/server/models/stash'
29
+
30
+ require 'vayacondios/server/handlers/document_handler'
31
+ require 'vayacondios/server/handlers/event_handler'
32
+ require 'vayacondios/server/handlers/events_handler'
33
+ require 'vayacondios/server/handlers/stash_handler'
34
+ require 'vayacondios/server/handlers/stashes_handler'
35
+ require 'vayacondios/server/handlers/stream_handler'
@@ -1,29 +1,35 @@
1
1
  require 'goliath'
2
+ require 'goliath/chimp'
2
3
  require 'em-mongo'
3
4
  require 'em-synchrony/em-http'
4
5
  require 'em-synchrony/em-mongo'
6
+ require 'configliere'
5
7
 
6
8
  require 'gorillib/object/blank'
7
9
  require 'gorillib/enumerable/sum'
10
+ require 'gorillib/hash/compact'
8
11
  require 'gorillib/hash/deep_merge'
9
12
  require 'gorillib/hash/keys'
13
+ require 'gorillib/model'
10
14
  require 'gorillib/string/constantize'
11
15
  require 'gorillib/string/inflections'
12
16
  require 'multi_json'
13
17
 
14
- require 'vayacondios/server/errors/bad_request'
15
- require 'vayacondios/server/errors/not_found'
18
+ require 'vayacondios'
19
+ require 'vayacondios/configuration'
16
20
 
17
- require 'vayacondios/server/model/config_document'
18
- require 'vayacondios/server/model/event_document'
19
- require 'vayacondios/server/model/itemset_document'
21
+ require 'vayacondios/server/api_options'
22
+ require 'vayacondios/server/configuration'
23
+ require 'vayacondios/server/driver'
24
+ require 'vayacondios/server/drivers/mongo'
20
25
 
21
- require 'vayacondios/server/handlers/config_handler'
22
- require 'vayacondios/server/handlers/event_handler'
23
- require 'vayacondios/server/handlers/itemset_handler'
26
+ require 'vayacondios/server/models/document'
27
+ require 'vayacondios/server/models/event'
28
+ require 'vayacondios/server/models/stash'
24
29
 
25
- require 'vayacondios/server/rack/extract_methods'
26
- require 'vayacondios/server/rack/params'
27
- require 'vayacondios/server/rack/jsonize'
28
- require 'vayacondios/server/rack/path'
29
- require 'vayacondios/server/rack/path_validation'
30
+ require 'vayacondios/server/handlers/document_handler'
31
+ require 'vayacondios/server/handlers/event_handler'
32
+ require 'vayacondios/server/handlers/events_handler'
33
+ require 'vayacondios/server/handlers/stash_handler'
34
+ require 'vayacondios/server/handlers/stashes_handler'
35
+ require 'vayacondios/server/handlers/stream_handler'
@@ -0,0 +1,22 @@
1
+ module Vayacondios
2
+ # Version of the api
3
+ API_VERSION = 'v3'
4
+
5
+ # Gem version for both client and server
6
+ GEM_VERSION = '0.3.0'
7
+
8
+ # Default port to find/connect to for the server
9
+ DEFAULT_SERVER_PORT = 3467
10
+
11
+ # Default address to bind/connect to for the server
12
+ DEFAULT_SERVER_ADDRESS = 'localhost'
13
+
14
+ module_function
15
+
16
+ def library_dir
17
+ File.expand_path('../..', __FILE__)
18
+ end
19
+ end
20
+
21
+ # Alias for Vayacondios
22
+ Vcd = Vayacondios