skydb 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +4 -0
- data/lib/ext/string.rb +11 -0
- data/lib/skydb.rb +88 -0
- data/lib/skydb/action.rb +57 -0
- data/lib/skydb/client.rb +216 -0
- data/lib/skydb/event.rb +114 -0
- data/lib/skydb/message.rb +134 -0
- data/lib/skydb/message/add_action.rb +53 -0
- data/lib/skydb/message/add_event.rb +72 -0
- data/lib/skydb/message/add_property.rb +55 -0
- data/lib/skydb/message/get_action.rb +55 -0
- data/lib/skydb/message/get_actions.rb +34 -0
- data/lib/skydb/message/get_properties.rb +34 -0
- data/lib/skydb/message/get_property.rb +55 -0
- data/lib/skydb/message/lua/map_reduce.rb +59 -0
- data/lib/skydb/message/multi.rb +57 -0
- data/lib/skydb/message/next_actions.rb +55 -0
- data/lib/skydb/property.rb +93 -0
- data/lib/skydb/property/type.rb +40 -0
- data/lib/skydb/timestamp.rb +22 -0
- data/lib/skydb/version.rb +3 -0
- data/test/client_test.rb +71 -0
- data/test/event_test.rb +37 -0
- data/test/message/add_action_message_test.rb +34 -0
- data/test/message/add_event_message_test.rb +35 -0
- data/test/message/add_property_message_test.rb +41 -0
- data/test/message/get_action_message_test.rb +34 -0
- data/test/message/get_actions_message_test.rb +18 -0
- data/test/message/get_properties_message_test.rb +18 -0
- data/test/message/get_property_message_test.rb +34 -0
- data/test/message/lua_map_reduce_message_test.rb +19 -0
- data/test/message/multi_message_test.rb +22 -0
- data/test/message/next_action_message_test.rb +34 -0
- data/test/message_test.rb +15 -0
- data/test/skydb_test.rb +20 -0
- data/test/test_helper.rb +12 -0
- metadata +166 -0
data/README.md
ADDED
data/lib/ext/string.rb
ADDED
data/lib/skydb.rb
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
require 'date'
|
2
|
+
require 'msgpack'
|
3
|
+
require 'socket'
|
4
|
+
|
5
|
+
require 'skydb/action'
|
6
|
+
require 'skydb/client'
|
7
|
+
require 'skydb/event'
|
8
|
+
require 'skydb/message'
|
9
|
+
require 'skydb/property'
|
10
|
+
require 'skydb/timestamp'
|
11
|
+
require 'skydb/version'
|
12
|
+
|
13
|
+
require 'ext/string'
|
14
|
+
|
15
|
+
class SkyDB
|
16
|
+
############################################################################
|
17
|
+
#
|
18
|
+
# Errors
|
19
|
+
#
|
20
|
+
############################################################################
|
21
|
+
|
22
|
+
class TableRequiredError < StandardError; end
|
23
|
+
|
24
|
+
class ObjectIdRequiredError < StandardError; end
|
25
|
+
class TimestampRequiredError < StandardError; end
|
26
|
+
|
27
|
+
############################################################################
|
28
|
+
#
|
29
|
+
# Constants
|
30
|
+
#
|
31
|
+
############################################################################
|
32
|
+
|
33
|
+
CLIENT_PASSTHROUGH = [
|
34
|
+
:host, :host=, :port, :port=,
|
35
|
+
:table, :table=,
|
36
|
+
:multi,
|
37
|
+
:add_event,
|
38
|
+
:add_action, :get_action, :get_actions,
|
39
|
+
:add_property, :get_property, :get_properties,
|
40
|
+
:next_actions,
|
41
|
+
:map_reduce
|
42
|
+
]
|
43
|
+
|
44
|
+
|
45
|
+
############################################################################
|
46
|
+
#
|
47
|
+
# Static Attributes
|
48
|
+
#
|
49
|
+
############################################################################
|
50
|
+
|
51
|
+
######################################
|
52
|
+
# Debugging
|
53
|
+
######################################
|
54
|
+
|
55
|
+
class << self
|
56
|
+
attr_accessor :debug
|
57
|
+
end
|
58
|
+
|
59
|
+
######################################
|
60
|
+
# Default Client
|
61
|
+
######################################
|
62
|
+
|
63
|
+
# The default Sky client.
|
64
|
+
def self.client
|
65
|
+
@client ||= SkyDB::Client.new()
|
66
|
+
return @client
|
67
|
+
end
|
68
|
+
|
69
|
+
def self.client=(value)
|
70
|
+
@client = value
|
71
|
+
end
|
72
|
+
|
73
|
+
|
74
|
+
############################################################################
|
75
|
+
#
|
76
|
+
# Static Methods
|
77
|
+
#
|
78
|
+
############################################################################
|
79
|
+
|
80
|
+
def self.method_missing(method, *args, &block)
|
81
|
+
method = method
|
82
|
+
if CLIENT_PASSTHROUGH.include?(method.to_sym)
|
83
|
+
client.__send__(method.to_sym, *args, &block)
|
84
|
+
else
|
85
|
+
raise NoMethodError.new("Message type not available: #{method}")
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
data/lib/skydb/action.rb
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
class SkyDB
|
2
|
+
class Action
|
3
|
+
##########################################################################
|
4
|
+
#
|
5
|
+
# Constructor
|
6
|
+
#
|
7
|
+
##########################################################################
|
8
|
+
|
9
|
+
# Initializes the action.
|
10
|
+
def initialize(options={})
|
11
|
+
self.id = options[:id]
|
12
|
+
self.name = options[:name]
|
13
|
+
end
|
14
|
+
|
15
|
+
|
16
|
+
##########################################################################
|
17
|
+
#
|
18
|
+
# Attributes
|
19
|
+
#
|
20
|
+
##########################################################################
|
21
|
+
|
22
|
+
##################################
|
23
|
+
# ID
|
24
|
+
##################################
|
25
|
+
|
26
|
+
# The action identifier.
|
27
|
+
attr_reader :id
|
28
|
+
|
29
|
+
def id=(value)
|
30
|
+
@id = value.to_i
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
##################################
|
35
|
+
# Name
|
36
|
+
##################################
|
37
|
+
|
38
|
+
# The name of the action.
|
39
|
+
attr_reader :name
|
40
|
+
|
41
|
+
def name=(value)
|
42
|
+
@name = value.to_s
|
43
|
+
end
|
44
|
+
|
45
|
+
|
46
|
+
##########################################################################
|
47
|
+
#
|
48
|
+
# Methods
|
49
|
+
#
|
50
|
+
##########################################################################
|
51
|
+
|
52
|
+
# Encodes the action into MsgPack format.
|
53
|
+
def to_msgpack
|
54
|
+
return {id:id, name:name}.to_msgpack
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
data/lib/skydb/client.rb
ADDED
@@ -0,0 +1,216 @@
|
|
1
|
+
class SkyDB
|
2
|
+
class Client
|
3
|
+
##########################################################################
|
4
|
+
#
|
5
|
+
# Constants
|
6
|
+
#
|
7
|
+
##########################################################################
|
8
|
+
|
9
|
+
# The default host to connect to if one is not specified.
|
10
|
+
DEFAULT_HOST = 'localhost'
|
11
|
+
|
12
|
+
# The default port to connect to if one is not specified.
|
13
|
+
DEFAULT_PORT = 8585
|
14
|
+
|
15
|
+
|
16
|
+
##########################################################################
|
17
|
+
#
|
18
|
+
# Constructor
|
19
|
+
#
|
20
|
+
##########################################################################
|
21
|
+
|
22
|
+
# Initializes the client.
|
23
|
+
def initialize(options={})
|
24
|
+
self.host = options[:host] || DEFAULT_HOST
|
25
|
+
self.port = options[:port] || DEFAULT_PORT
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
##########################################################################
|
30
|
+
#
|
31
|
+
# Attributes
|
32
|
+
#
|
33
|
+
##########################################################################
|
34
|
+
|
35
|
+
# The name of the host to conect to.
|
36
|
+
attr_accessor :host
|
37
|
+
|
38
|
+
# The port on the host to connect to.
|
39
|
+
attr_accessor :port
|
40
|
+
|
41
|
+
# The table to connect to.
|
42
|
+
attr_accessor :table
|
43
|
+
|
44
|
+
|
45
|
+
##########################################################################
|
46
|
+
#
|
47
|
+
# Methods
|
48
|
+
#
|
49
|
+
##########################################################################
|
50
|
+
|
51
|
+
####################################
|
52
|
+
# Action Messages
|
53
|
+
####################################
|
54
|
+
|
55
|
+
# Adds an action to the server.
|
56
|
+
#
|
57
|
+
# @param [Action] action the action to add.
|
58
|
+
def add_action(action, options={})
|
59
|
+
return send_message(SkyDB::Message::AddAction.new(action, options))
|
60
|
+
end
|
61
|
+
|
62
|
+
# Retrieves an individual action from the server.
|
63
|
+
#
|
64
|
+
# @param [Fixnum] action_id the identifier of the action to retrieve.
|
65
|
+
def get_action(action_id, options={})
|
66
|
+
return send_message(SkyDB::Message::GetAction.new(action_id, options))
|
67
|
+
end
|
68
|
+
|
69
|
+
# Retrieves a list of all actions from the server.
|
70
|
+
def get_actions(options={})
|
71
|
+
return send_message(SkyDB::Message::GetActions.new(options))
|
72
|
+
end
|
73
|
+
|
74
|
+
|
75
|
+
####################################
|
76
|
+
# Property Messages
|
77
|
+
####################################
|
78
|
+
|
79
|
+
# Adds a property to the server.
|
80
|
+
#
|
81
|
+
# @param [Property] property the property to add.
|
82
|
+
def add_property(property, options={})
|
83
|
+
return send_message(SkyDB::Message::AddProperty.new(property, options))
|
84
|
+
end
|
85
|
+
|
86
|
+
# Retrieves an individual property from the server.
|
87
|
+
#
|
88
|
+
# @param [Fixnum] property_id the identifier of the property to retrieve.
|
89
|
+
def get_property(property_id, options={})
|
90
|
+
return send_message(SkyDB::Message::GetProperty.new(property_id, options))
|
91
|
+
end
|
92
|
+
|
93
|
+
# Retrieves a list of all properties from the server.
|
94
|
+
def get_properties(options={})
|
95
|
+
return send_message(SkyDB::Message::GetProperties.new(options))
|
96
|
+
end
|
97
|
+
|
98
|
+
|
99
|
+
####################################
|
100
|
+
# Event Messages
|
101
|
+
####################################
|
102
|
+
|
103
|
+
# Adds an event to the server.
|
104
|
+
#
|
105
|
+
# @param [Event] event the event to add.
|
106
|
+
def add_event(event, options={})
|
107
|
+
return send_message(SkyDB::Message::AddEvent.new(event, options))
|
108
|
+
end
|
109
|
+
|
110
|
+
|
111
|
+
####################################
|
112
|
+
# Path Messages
|
113
|
+
####################################
|
114
|
+
|
115
|
+
# Finds a count of the action that occurs immediately after a set of
|
116
|
+
# actions.
|
117
|
+
#
|
118
|
+
# @param [Array] prior_action_ids the prior action ids to match on.
|
119
|
+
def next_actions(prior_action_ids, options={})
|
120
|
+
return send_message(SkyDB::Message::NextActions.new(prior_action_ids, options))
|
121
|
+
end
|
122
|
+
|
123
|
+
|
124
|
+
####################################
|
125
|
+
# Lua Messages
|
126
|
+
####################################
|
127
|
+
|
128
|
+
# Executes a Lua map/reduce job on the server and returns the results.
|
129
|
+
#
|
130
|
+
# @param [String] source the Lua source code to execute
|
131
|
+
def map_reduce(source, options={})
|
132
|
+
return send_message(SkyDB::Message::Lua::MapReduce.new(source, options))
|
133
|
+
end
|
134
|
+
|
135
|
+
|
136
|
+
####################################
|
137
|
+
# Multi message
|
138
|
+
####################################
|
139
|
+
|
140
|
+
# Executes multiple messages in one call.
|
141
|
+
def multi(options={})
|
142
|
+
raise "Already in a multi-message block" unless @multi_message.nil?
|
143
|
+
|
144
|
+
# Create multi-message.
|
145
|
+
@multi_message = SkyDB::Message::Multi.new(options)
|
146
|
+
|
147
|
+
# Execute the block normally and send the message.
|
148
|
+
begin
|
149
|
+
yield
|
150
|
+
|
151
|
+
# Clear multi message so it doesn't add to itself.
|
152
|
+
tmp = @multi_message
|
153
|
+
@multi_message = nil
|
154
|
+
|
155
|
+
# Send all messages at once.
|
156
|
+
send_message(tmp)
|
157
|
+
|
158
|
+
ensure
|
159
|
+
@multi_message = nil
|
160
|
+
end
|
161
|
+
|
162
|
+
return nil
|
163
|
+
end
|
164
|
+
|
165
|
+
|
166
|
+
####################################
|
167
|
+
# Send
|
168
|
+
####################################
|
169
|
+
|
170
|
+
# Sends a message to the server.
|
171
|
+
#
|
172
|
+
# @param [SkyDB::Message] message the message to send.
|
173
|
+
# @return [Object] the object returned by the server.
|
174
|
+
def send_message(message)
|
175
|
+
# Set the table if they're not set.
|
176
|
+
message.table = table if message.table.nil? || message.table.empty?
|
177
|
+
|
178
|
+
# Validate message before sending.
|
179
|
+
message.validate!
|
180
|
+
|
181
|
+
# If this is part of a multi message then simply append the message for
|
182
|
+
# later sending.
|
183
|
+
if !@multi_message.nil?
|
184
|
+
@multi_message.messages << message
|
185
|
+
return nil
|
186
|
+
|
187
|
+
# Otherwise send the message immediately.
|
188
|
+
else
|
189
|
+
# Connect to the server.
|
190
|
+
socket = TCPSocket.new(host, port.to_i)
|
191
|
+
|
192
|
+
# Encode and send message request.
|
193
|
+
message.encode(socket)
|
194
|
+
|
195
|
+
# Decode msgpack response. There should only be one return object.
|
196
|
+
response = nil
|
197
|
+
unpacker = MessagePack::Unpacker.new(socket)
|
198
|
+
unpacker.each do |obj|
|
199
|
+
response = obj
|
200
|
+
break
|
201
|
+
end
|
202
|
+
|
203
|
+
# Close socket.
|
204
|
+
socket.close()
|
205
|
+
|
206
|
+
# TODO: Exception processing.
|
207
|
+
|
208
|
+
# Process response back through the message.
|
209
|
+
response = message.process_response(response)
|
210
|
+
|
211
|
+
# Return response.
|
212
|
+
return response
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end
|
216
|
+
end
|
data/lib/skydb/event.rb
ADDED
@@ -0,0 +1,114 @@
|
|
1
|
+
class SkyDB
|
2
|
+
class Event
|
3
|
+
##########################################################################
|
4
|
+
#
|
5
|
+
# Constructor
|
6
|
+
#
|
7
|
+
##########################################################################
|
8
|
+
|
9
|
+
# Initializes an event object.
|
10
|
+
def initialize(options={})
|
11
|
+
self.object_id = options[:object_id]
|
12
|
+
self.timestamp = options[:timestamp]
|
13
|
+
self.action = options[:action]
|
14
|
+
self.data = options[:data]
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
##########################################################################
|
19
|
+
#
|
20
|
+
# Attributes
|
21
|
+
#
|
22
|
+
##########################################################################
|
23
|
+
|
24
|
+
##################################
|
25
|
+
# Object ID
|
26
|
+
##################################
|
27
|
+
|
28
|
+
# The numeric identifier of the object that the event is attached to.
|
29
|
+
attr_reader :object_id
|
30
|
+
|
31
|
+
def object_id=(value)
|
32
|
+
@object_id = value.to_i
|
33
|
+
end
|
34
|
+
|
35
|
+
##################################
|
36
|
+
# Timestamp
|
37
|
+
##################################
|
38
|
+
|
39
|
+
# The timestamp of when the event occurred.
|
40
|
+
attr_reader :timestamp
|
41
|
+
|
42
|
+
def timestamp=(value)
|
43
|
+
@timestamp = value.to_time if value.class.method_defined?(:to_time)
|
44
|
+
end
|
45
|
+
|
46
|
+
##################################
|
47
|
+
# Action
|
48
|
+
##################################
|
49
|
+
|
50
|
+
# The hash containing action related information (including the name of
|
51
|
+
# the action being performed).
|
52
|
+
attr_reader :action
|
53
|
+
|
54
|
+
def action=(value)
|
55
|
+
clone = {}
|
56
|
+
|
57
|
+
# Copy over keys
|
58
|
+
if !value.nil?
|
59
|
+
value.each_pair do |k, v|
|
60
|
+
# Only copy keys with valid value types.
|
61
|
+
if v.is_a?(String) || v.is_a?(Fixnum) || v.is_a?(Float) || v == true || v == false
|
62
|
+
clone[k] = value[k]
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# Only set the data if we have keys.
|
68
|
+
@action = clone.keys.length > 0 ? clone : nil
|
69
|
+
end
|
70
|
+
|
71
|
+
##################################
|
72
|
+
# Data
|
73
|
+
##################################
|
74
|
+
|
75
|
+
# A hash of data properties to set on the event. Properties can only be
|
76
|
+
# a String, Fixnum, Float or Boolean.
|
77
|
+
attr_reader :data
|
78
|
+
|
79
|
+
def data=(value)
|
80
|
+
clone = {}
|
81
|
+
|
82
|
+
# Copy over keys
|
83
|
+
if !value.nil?
|
84
|
+
value.each_pair do |k, v|
|
85
|
+
# Only copy keys with valid value types.
|
86
|
+
if v.is_a?(String) || v.is_a?(Fixnum) || v.is_a?(Float) || v == true || v == false
|
87
|
+
clone[k] = value[k]
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
# Only set the data if we have keys.
|
93
|
+
@data = clone.keys.length > 0 ? clone : nil
|
94
|
+
end
|
95
|
+
|
96
|
+
|
97
|
+
##########################################################################
|
98
|
+
#
|
99
|
+
# Methods
|
100
|
+
#
|
101
|
+
##########################################################################
|
102
|
+
|
103
|
+
# Encodes the event into MsgPack format.
|
104
|
+
def to_msgpack
|
105
|
+
obj = {
|
106
|
+
:objectId => object_id,
|
107
|
+
:timestamp => SkyDB::Timestamp.to_timestamp(timestamp)
|
108
|
+
}
|
109
|
+
obj[:action] = action unless action.nil? || action.empty?
|
110
|
+
obj[:data] = data unless data.nil? || data.empty?
|
111
|
+
return obj.to_msgpack
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|