rhosync 2.0.8 → 2.0.9
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/CHANGELOG +9 -0
- data/Rakefile +1 -5
- data/doc/protocol.html +397 -156
- data/lib/rhosync/console/app/public/ThickBox.css +649 -0
- data/lib/rhosync/console/app/public/home.css +433 -0
- data/lib/rhosync/console/app/public/images/header_halo copy.jpg +0 -0
- data/lib/rhosync/console/app/public/images/header_halo.jpg +0 -0
- data/lib/rhosync/console/app/public/images/land_separator.gif +0 -0
- data/lib/rhosync/console/app/public/images/landing_header.jpg +0 -0
- data/lib/rhosync/console/app/public/images/logo_rhosync.png +0 -0
- data/lib/rhosync/console/app/public/images/rhomobile_rhohub_logo.png +0 -0
- data/lib/rhosync/console/app/public/images/tabs_separator.png +0 -0
- data/lib/rhosync/console/app/public/reset.css +76 -0
- data/lib/rhosync/console/app/public/style.css +2201 -0
- data/lib/rhosync/console/app/routes/auth.rb +1 -1
- data/lib/rhosync/console/app/routes/client.rb +1 -1
- data/lib/rhosync/console/app/routes/docs.rb +98 -55
- data/lib/rhosync/console/app/routes/home.rb +47 -8
- data/lib/rhosync/console/app/routes/timing.rb +26 -0
- data/lib/rhosync/console/app/routes/user.rb +58 -21
- data/lib/rhosync/console/app/views/client.erb +2 -2
- data/lib/rhosync/console/app/views/content.erb +14 -0
- data/lib/rhosync/console/app/views/docdata.erb +1 -1
- data/lib/rhosync/console/app/views/docs.erb +2 -2
- data/lib/rhosync/console/app/views/headermenu.erb +41 -0
- data/lib/rhosync/console/app/views/home.erb +22 -0
- data/lib/rhosync/console/app/views/index.erb +1 -1
- data/lib/rhosync/console/app/views/layout.erb +82 -7
- data/lib/rhosync/console/app/views/login.erb +26 -0
- data/lib/rhosync/console/app/views/newuser.erb +1 -1
- data/lib/rhosync/console/app/views/result.erb +1 -1
- data/lib/rhosync/console/app/views/rightboxlinks.erb +15 -0
- data/lib/rhosync/console/app/views/select_doc.erb +1 -3
- data/lib/rhosync/console/app/views/user.erb +3 -6
- data/lib/rhosync/console/app/views/users.erb +2 -4
- data/lib/rhosync/console/server.rb +6 -0
- data/lib/rhosync/jobs/bulk_data_job.rb +17 -4
- data/lib/rhosync/ping/android.rb +38 -0
- data/lib/rhosync/ping.rb +2 -1
- data/lib/rhosync/server/views/index.erb +3 -0
- data/lib/rhosync/server.rb +25 -6
- data/lib/rhosync/source_sync.rb +14 -6
- data/lib/rhosync/stats/middleware.rb +22 -0
- data/lib/rhosync/stats/record.rb +83 -0
- data/lib/rhosync/version.rb +1 -1
- data/lib/rhosync.rb +4 -2
- data/spec/ping/android_spec.rb +45 -0
- data/spec/rhosync_spec.rb +1 -0
- data/spec/server/server_spec.rb +8 -0
- data/spec/spec.opts +3 -0
- data/spec/spec_helper.rb +4 -3
- data/spec/stats/middleware_spec.rb +32 -0
- data/spec/stats/record_spec.rb +71 -0
- metadata +31 -7
- data/lib/rhosync/monitoring/record.rb +0 -28
- data/spec/monitoring/record_spec.rb +0 -21
@@ -0,0 +1,15 @@
|
|
1
|
+
<!-- div, links[]{ :url, :title, :selected }> -->
|
2
|
+
|
3
|
+
<div id="right-box_links">
|
4
|
+
<ul class="right-box_links">
|
5
|
+
<% i=1 %>
|
6
|
+
<% links.each do |link| %>
|
7
|
+
<li><a id="link<%=i%>"
|
8
|
+
<%= 'class="selected"' if link[:selected] %>
|
9
|
+
onclick="javascript:loadXMLDoc('<%=link[:url]%>','<%= div %>');switch_tab(this.id); this.blur();"
|
10
|
+
href="javascript:void(0);"><%=link[:title]%></a>
|
11
|
+
</li>
|
12
|
+
<% i = i + 1 %>
|
13
|
+
<% end %>
|
14
|
+
</ul>
|
15
|
+
</div>
|
@@ -1,8 +1,5 @@
|
|
1
1
|
<h1>User: <%=params[:user_id]%></h1>
|
2
2
|
<%=show_errors%>
|
3
|
-
<div class="panel">
|
4
|
-
<a href="<%=url('users')%>" class='nav_button'>Back</a>
|
5
|
-
</div>
|
6
3
|
<div class="panel">
|
7
4
|
<a href='<%=url("user/delete?user_id=#{CGI.escape(params[:user_id])}")%>' class='nav_button'>Delete user</a>
|
8
5
|
</div>
|
@@ -13,18 +10,18 @@
|
|
13
10
|
|
14
11
|
[
|
15
12
|
<%@sources.each_index do |i|%>
|
16
|
-
<a href="<%=url("docs?source_id=#{@sources[i]}&user_id=#{CGI.escape(params[:user_id])}")%>"><%=i==0?'':','%>"<%=@sources[i]%>"</a>
|
13
|
+
<a href='javascript:void(0);' onclick="loadXMLDoc('<%=url("docs?source_id=#{@sources[i]}&user_id=#{CGI.escape(params[:user_id])}")%>','main_box');"><%=i==0?'':','%>"<%=@sources[i]%>"</a>
|
17
14
|
<%end%>
|
18
15
|
]
|
19
16
|
|
20
17
|
<h2>Registered Devices</h2>
|
21
18
|
|
22
|
-
<a href="<%=url("device/create?user_id=#{CGI.escape(params[:user_id])}")%>" class='nav_button'>Create Device</a>
|
19
|
+
<a href="javascript:void(0);" onclick="loadXMLDoc('<%=url("device/create?user_id=#{CGI.escape(params[:user_id])}")%>','');loadXMLDoc('<%=url("user?user_id=#{CGI.escape(params[:user_id])}")%>','main_box');" class='nav_button'>Create Device</a>
|
23
20
|
|
24
21
|
<div class="panel">
|
25
22
|
[
|
26
23
|
<%@devices.each_index do |i|%>
|
27
|
-
<a href="<%=url("device?user_id=#{CGI.escape(params[:user_id])}&device_id=#{CGI.escape(@devices[i])}")%>">
|
24
|
+
<a href="javascript:void(0);" onclick="loadXMLDoc('<%=url("device?user_id=#{CGI.escape(params[:user_id])}&device_id=#{CGI.escape(@devices[i])}")%>','main_box');">
|
28
25
|
<%=i==0?'':','%>"<%=@devices[i]%>"
|
29
26
|
</a>
|
30
27
|
<%end%>
|
@@ -1,6 +1,4 @@
|
|
1
|
-
<
|
2
|
-
<a href="<%=url('/')%>" class='nav_button'>Back</a>
|
3
|
-
<a href="<%=url('user/new')%>" class='nav_button'>Create User</a>
|
1
|
+
<a href="javascript:void(0);" onclick="loadXMLDoc('<%=url('user/new')%>','main_box');" class='nav_button'>Create User</a>
|
4
2
|
|
5
3
|
<h2>Registered users</h2>
|
6
4
|
<%if is_errors?%>
|
@@ -8,7 +6,7 @@
|
|
8
6
|
<%else%>
|
9
7
|
[
|
10
8
|
<%@users.each_index do |i|%>
|
11
|
-
<a href="<%=url("user?user_id=#{CGI.escape(@users[i])}")%>"><%=i==0?'':','%>"<%=@users[i]%>"</a>
|
9
|
+
<a href="javascript:void(0);" onclick="loadXMLDoc('<%=url("user?user_id=#{CGI.escape(@users[i])}")%>','main_box');"><%=i==0?'':','%>"<%=@users[i]%>"</a>
|
12
10
|
<%end%>
|
13
11
|
]
|
14
12
|
<%end%>
|
@@ -19,6 +19,12 @@ module RhosyncConsole
|
|
19
19
|
set :public, RhosyncConsole::root_path("app","public")
|
20
20
|
set :static, true
|
21
21
|
use Rack::Session::Cookie
|
22
|
+
before do
|
23
|
+
headers['Expires'] = 'Sun, 19 Nov 1978 05:00:00 GMT'
|
24
|
+
headers['Cache-Control'] = 'no-store, no-cache, must-revalidate'
|
25
|
+
headers['Pramga'] = 'no-cache'
|
26
|
+
end
|
27
|
+
|
22
28
|
end
|
23
29
|
end
|
24
30
|
|
@@ -16,6 +16,7 @@ module Rhosync
|
|
16
16
|
ts = Time.now.to_i.to_s
|
17
17
|
create_sqlite_data_file(bulk_data,ts)
|
18
18
|
timer = lap_timer('create_sqlite_data_file',timer)
|
19
|
+
log " bulk_data.dbfile : #{bulk_data.dbfile}"
|
19
20
|
create_hsql_data_file(bulk_data,ts) if Rhosync.blackberry_bulk_sync
|
20
21
|
lap_timer('create_hsql_data_file',timer)
|
21
22
|
log "finished bulk data process"
|
@@ -54,13 +55,13 @@ module Rhosync
|
|
54
55
|
data = source.get_data(:md)
|
55
56
|
counter = {}
|
56
57
|
columns,qm = [],[]
|
57
|
-
create_table = [
|
58
|
+
create_table = ["\"object\" varchar"]
|
58
59
|
schema = JSON.parse(source.schema)
|
59
60
|
|
60
61
|
db.transaction do |database|
|
61
62
|
# Create a table with columns specified by 'property' array in settings
|
62
63
|
schema['property'].each do |key,value|
|
63
|
-
create_table << "#{key} varchar default NULL"
|
64
|
+
create_table << "\"#{key}\" varchar default NULL"
|
64
65
|
columns << key
|
65
66
|
qm << '?'
|
66
67
|
end
|
@@ -81,12 +82,24 @@ module Rhosync
|
|
81
82
|
|
82
83
|
# Create indexes for specified columns in settings 'index'
|
83
84
|
schema['index'].each do |key,value|
|
84
|
-
|
85
|
+
val2 = ""
|
86
|
+
value.split(',').each do |col|
|
87
|
+
val2 += ',' if val2.length() > 0
|
88
|
+
val2 += "\"#{col}\""
|
89
|
+
end
|
90
|
+
|
91
|
+
database.execute("CREATE INDEX #{key} on #{source.name} (#{val2});")
|
85
92
|
end if schema['index']
|
86
93
|
|
87
94
|
# Create unique indexes for specified columns in settings 'unique_index'
|
88
95
|
schema['unique_index'].each do |key,value|
|
89
|
-
|
96
|
+
val2 = ""
|
97
|
+
value.split(',').each do |col|
|
98
|
+
val2 += ',' if val2.length() > 0
|
99
|
+
val2 += "\"#{col}\""
|
100
|
+
end
|
101
|
+
|
102
|
+
database.execute("CREATE UNIQUE INDEX #{key} on #{source.name} (#{val2});")
|
90
103
|
end if schema['unique_index']
|
91
104
|
end
|
92
105
|
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'net/https'
|
2
|
+
require 'uri'
|
3
|
+
module Rhosync
|
4
|
+
class Android
|
5
|
+
def self.ping(params)
|
6
|
+
begin
|
7
|
+
settings = get_config(Rhosync.base_directory)[Rhosync.environment]
|
8
|
+
authtoken = settings[:authtoken]
|
9
|
+
|
10
|
+
url = URI.parse('https://android.apis.google.com/c2dm/send')
|
11
|
+
|
12
|
+
req = Net::HTTP::Post.new url.path, 'Authorization' => "GoogleLogin auth=#{authtoken}"
|
13
|
+
req.set_form_data c2d_message(params)
|
14
|
+
|
15
|
+
http = Net::HTTP.new(url.host, url.port)
|
16
|
+
http.use_ssl = true
|
17
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
18
|
+
res = http.request(req)
|
19
|
+
|
20
|
+
rescue Exception => error
|
21
|
+
log "Error while sending ping: #{error}"
|
22
|
+
raise error
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.c2d_message(params)
|
27
|
+
data = {}
|
28
|
+
data['registration_id'] = params['device_pin']
|
29
|
+
data['collapse_key'] = (rand * 100000000).to_i.to_s
|
30
|
+
data['data.do_sync'] = params['sources'] ? params['sources'].join(',') : ''
|
31
|
+
data['data.alert'] = params['message'] if params['message']
|
32
|
+
data['data.vibrate'] = params['vibrate'] if params['vibrate']
|
33
|
+
data['data.sound'] = params['sound'] if params['sound']
|
34
|
+
|
35
|
+
data
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
data/lib/rhosync/ping.rb
CHANGED
data/lib/rhosync/server.rb
CHANGED
@@ -21,12 +21,12 @@ module Rhosync
|
|
21
21
|
set :public, "#{libdir}/server/public"
|
22
22
|
set :static, true
|
23
23
|
|
24
|
-
|
24
|
+
# default secret
|
25
|
+
@@secret = '<changeme>'
|
25
26
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
27
|
+
# stats middleware disabled by default
|
28
|
+
@@stats = false
|
29
|
+
|
30
30
|
# Setup route and mimetype for bulk data downloads
|
31
31
|
# TODO: Figure out why "mime :data, 'application/octet-stream'" doesn't work
|
32
32
|
Rack::Mime::MIME_TYPES['.data'] = 'application/octet-stream'
|
@@ -126,10 +126,29 @@ module Rhosync
|
|
126
126
|
end
|
127
127
|
end
|
128
128
|
end
|
129
|
+
|
130
|
+
# hook into new so we can enable middleware
|
131
|
+
def self.new
|
132
|
+
if @@stats == true
|
133
|
+
use Rhosync::Stats::Middleware
|
134
|
+
Rhosync.stats = true
|
135
|
+
end
|
136
|
+
use Rack::Session::Cookie,
|
137
|
+
:key => 'rhosync_session',
|
138
|
+
:expire_after => 31536000,
|
139
|
+
:secret => @@secret
|
140
|
+
super
|
141
|
+
end
|
142
|
+
|
143
|
+
def self.set(option, value=self, &block)
|
144
|
+
@@stats = value if option == :stats and (value.is_a?(TrueClass) or value.is_a?(FalseClass))
|
145
|
+
@@secret = value if option == :secret and value.is_a?(String)
|
146
|
+
super
|
147
|
+
end
|
129
148
|
|
130
149
|
def initialize
|
131
150
|
# Whine about default session secret
|
132
|
-
check_default_secret!(
|
151
|
+
check_default_secret!(@@secret)
|
133
152
|
super
|
134
153
|
end
|
135
154
|
|
data/lib/rhosync/source_sync.rb
CHANGED
@@ -11,15 +11,15 @@ module Rhosync
|
|
11
11
|
|
12
12
|
# CUD Operations
|
13
13
|
def create(client_id)
|
14
|
-
|
14
|
+
_measure_and_process_cud('create',client_id)
|
15
15
|
end
|
16
16
|
|
17
17
|
def update(client_id)
|
18
|
-
|
18
|
+
_measure_and_process_cud('update',client_id)
|
19
19
|
end
|
20
20
|
|
21
21
|
def delete(client_id)
|
22
|
-
|
22
|
+
_measure_and_process_cud('delete',client_id)
|
23
23
|
end
|
24
24
|
|
25
25
|
# Read Operation; params are query arguments
|
@@ -60,9 +60,11 @@ module Rhosync
|
|
60
60
|
|
61
61
|
def do_query(params=nil)
|
62
62
|
@source.if_need_refresh do
|
63
|
-
|
64
|
-
|
65
|
-
|
63
|
+
Stats::Record.update("source:query:#{@source.name}") do
|
64
|
+
return if _auth_op('login') == false
|
65
|
+
self.read(nil,params)
|
66
|
+
_auth_op('logoff')
|
67
|
+
end
|
66
68
|
end
|
67
69
|
end
|
68
70
|
|
@@ -143,6 +145,12 @@ module Rhosync
|
|
143
145
|
dels[key] = value
|
144
146
|
end
|
145
147
|
|
148
|
+
def _measure_and_process_cud(operation,client_id)
|
149
|
+
Stats::Record.update("source:#{operation}:#{@source.name}") do
|
150
|
+
_process_cud(operation,client_id)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
146
154
|
def _process_cud(operation,client_id)
|
147
155
|
errors,links,deletes,creates,dels = {},{},{},{},{}
|
148
156
|
client = Client.load(client_id,{:source_name => @source.name})
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Rhosync
|
2
|
+
module Stats
|
3
|
+
class Middleware
|
4
|
+
def initialize(app)
|
5
|
+
@app = app
|
6
|
+
end
|
7
|
+
|
8
|
+
def call(env)
|
9
|
+
start = Time.now.to_f
|
10
|
+
status, headers, body = @app.call(env)
|
11
|
+
finish = Time.now.to_f
|
12
|
+
metric = "http:#{env['REQUEST_METHOD']}:#{env['REQUEST_PATH']}"
|
13
|
+
source_id = env['rack.request.query_hash']["source_id"] if env['rack.request.query_hash']
|
14
|
+
metric << ":#{source_id}" if source_id
|
15
|
+
Record.add(metric,finish - start) do |counter,aggregate|
|
16
|
+
Record.save_average(counter,aggregate)
|
17
|
+
end
|
18
|
+
[status, headers, body]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
module Rhosync
|
2
|
+
module Stats
|
3
|
+
class Record
|
4
|
+
class << self
|
5
|
+
|
6
|
+
# Add a value to a metric. If zset already has a member,
|
7
|
+
# update the existing member with an incremented value by default.
|
8
|
+
# Also supports updating the value with a block (useful for averages)
|
9
|
+
def add(metric, value = 1)
|
10
|
+
start = Time.now.to_i
|
11
|
+
current, current_score = 0, start
|
12
|
+
range = Store.db.zrevrange(key(metric), 0, 0)
|
13
|
+
if !range.empty?
|
14
|
+
member = range[0]
|
15
|
+
m_current = member.split(':')[0]
|
16
|
+
m_current_score = Store.db.zscore(key(metric), member).to_i
|
17
|
+
if m_current_score > (start - resolution(metric))
|
18
|
+
Store.db.zrem(key(metric), member)
|
19
|
+
current, current_score = m_current, m_current_score
|
20
|
+
end
|
21
|
+
end
|
22
|
+
value = block_given? ? yield(current, value) : (current.to_i + value)
|
23
|
+
Store.db.zadd(key(metric), current_score, "#{value}:#{start}")
|
24
|
+
Store.db.zremrangebyscore(key(metric), 0, start - record_size(metric))
|
25
|
+
end
|
26
|
+
|
27
|
+
# Saves the accumulated average for a resolution in a metric
|
28
|
+
def save_average(current, value)
|
29
|
+
sum = value
|
30
|
+
if current.is_a?(String)
|
31
|
+
current,sum = current.split(',')
|
32
|
+
current = current.to_f
|
33
|
+
sum = sum.to_f+value
|
34
|
+
end
|
35
|
+
"#{current + 1},#{sum}"
|
36
|
+
end
|
37
|
+
|
38
|
+
def update(metric)
|
39
|
+
if Rhosync.stats
|
40
|
+
start = Time.now.to_f
|
41
|
+
# perform the operations
|
42
|
+
yield
|
43
|
+
finish = Time.now.to_f
|
44
|
+
add(metric, finish - start) do |counter, aggregate|
|
45
|
+
save_average(counter, aggregate)
|
46
|
+
end
|
47
|
+
else
|
48
|
+
yield
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def reset(metric)
|
53
|
+
Store.db.del(key(metric))
|
54
|
+
end
|
55
|
+
|
56
|
+
def reset_all
|
57
|
+
Store.flash_data('stat:*')
|
58
|
+
end
|
59
|
+
|
60
|
+
# Returns the metric data, uses array indexing
|
61
|
+
def range(metric, start, finish = -1)
|
62
|
+
Store.db.zrange(key(metric), start, finish)
|
63
|
+
end
|
64
|
+
|
65
|
+
# Returns the resolution for a given metric, default 60 seconds
|
66
|
+
def resolution(metric)
|
67
|
+
resolution = Object.const_get("#{metric.upcase}_RECORD_RESOLUTION") rescue nil
|
68
|
+
resolution || 60 #=> 1 minute aggregate
|
69
|
+
end
|
70
|
+
|
71
|
+
# Returns the # of records to save for a given metric
|
72
|
+
def record_size(metric)
|
73
|
+
size = Object.const_get("#{metric.upcase}_RECORD_SIZE") rescue nil
|
74
|
+
size || 60 * 24 * 31 #=> 44640 minutes
|
75
|
+
end
|
76
|
+
|
77
|
+
def key(metric)
|
78
|
+
"stat:#{metric}"
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
data/lib/rhosync/version.rb
CHANGED
data/lib/rhosync.rb
CHANGED
@@ -21,7 +21,8 @@ require 'rhosync/source_sync'
|
|
21
21
|
require 'rhosync/rho_indifferent_access'
|
22
22
|
require 'rhosync/jobs/source_job'
|
23
23
|
require 'rhosync/jobs/ping_job'
|
24
|
-
require 'rhosync/
|
24
|
+
require 'rhosync/stats/record'
|
25
|
+
require 'rhosync/stats/middleware'
|
25
26
|
require 'rhosync/bulk_data'
|
26
27
|
|
27
28
|
REDIS_URL = 'REDIS' unless defined? REDIS_URL
|
@@ -41,7 +42,7 @@ module Rhosync
|
|
41
42
|
class << self
|
42
43
|
attr_accessor :base_directory, :app_directory, :data_directory,
|
43
44
|
:vendor_directory, :blackberry_bulk_sync, :redis, :environment,
|
44
|
-
:log_disabled, :license, :bulk_sync_poll_interval
|
45
|
+
:log_disabled, :license, :bulk_sync_poll_interval, :stats
|
45
46
|
end
|
46
47
|
|
47
48
|
### Begin Rhosync setup methods
|
@@ -70,6 +71,7 @@ module Rhosync
|
|
70
71
|
Rhosync.blackberry_bulk_sync ||= false
|
71
72
|
Rhosync.bulk_sync_poll_interval ||= 3600
|
72
73
|
Rhosync.log_disabled ||= false
|
74
|
+
Rhosync.stats ||= false
|
73
75
|
Rhosync.license = License.new
|
74
76
|
|
75
77
|
check_and_add(File.join(Rhosync.app_directory,'sources'))
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__),'..','spec_helper')
|
2
|
+
|
3
|
+
describe "Ping Android" do
|
4
|
+
it_should_behave_like "SpecBootstrapHelper"
|
5
|
+
it_should_behave_like "SourceAdapterHelper"
|
6
|
+
|
7
|
+
before do
|
8
|
+
@params = {"device_pin" => @c.device_pin,
|
9
|
+
"sources" => [@s.name], "message" => 'hello world',
|
10
|
+
"vibrate" => '5', "badge" => '5', "sound" => 'hello.mp3'}
|
11
|
+
post = mock('post')
|
12
|
+
post.stub!(:new).and_return(post)
|
13
|
+
post.stub!(:set_form_data)
|
14
|
+
Net::HTTP::Post.stub!(:new).and_return(post)
|
15
|
+
|
16
|
+
@http = mock('http')
|
17
|
+
@http.stub!(:request)
|
18
|
+
@http.stub!(:use_ssl=)
|
19
|
+
@http.stub!(:verify_mode=)
|
20
|
+
@http.stub!(:start).and_yield(@http)
|
21
|
+
Net::HTTP.stub!(:new).and_return(@http)
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should ping android" do
|
25
|
+
Android.ping(@params)
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should ping android with connection error" do
|
29
|
+
error = 'Connection refused'
|
30
|
+
@http.stub!(:request).and_return { raise SocketError.new(error) }
|
31
|
+
Android.should_receive(:log).once.with("Error while sending ping: #{error}")
|
32
|
+
lambda { Android.ping(@params) }.should raise_error(SocketError,error)
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should compute c2d_message" do
|
36
|
+
expected = {'registration_id' => @c.device_pin, 'collapse_key' => "RAND_KEY",
|
37
|
+
'data.do_sync' => @s.name,
|
38
|
+
'data.alert' => "hello world",
|
39
|
+
'data.vibrate' => '5',
|
40
|
+
'data.sound' => "hello.mp3"}
|
41
|
+
actual = Android.c2d_message(@params)
|
42
|
+
actual['collapse_key'] = "RAND_KEY" unless actual['collapse_key'].nil?
|
43
|
+
actual.should == expected
|
44
|
+
end
|
45
|
+
end
|
data/spec/rhosync_spec.rb
CHANGED
data/spec/server/server_spec.rb
CHANGED
@@ -57,6 +57,14 @@ describe "Server" do
|
|
57
57
|
Rhosync::Server.secret.should == "secure!"
|
58
58
|
end
|
59
59
|
|
60
|
+
it "should use Stats::Middleware if stats enabled" do
|
61
|
+
Rhosync::Server.enable :stats
|
62
|
+
Rhosync::Server.new
|
63
|
+
Rhosync.stats.should == true
|
64
|
+
Rhosync.stats = nil
|
65
|
+
Rhosync::Server.disable :stats
|
66
|
+
end
|
67
|
+
|
60
68
|
it "should update session secret to default" do
|
61
69
|
Rhosync::Server.set :secret, "<changeme>"
|
62
70
|
Rhosync::Server.secret.should == "<changeme>"
|
data/spec/spec.opts
ADDED
data/spec/spec_helper.rb
CHANGED
@@ -117,9 +117,9 @@ module TestHelpers
|
|
117
117
|
db.execute("select source_id,name,sync_priority,partition,
|
118
118
|
sync_type,source_attribs,metadata,blob_attribs,associations
|
119
119
|
from sources where name='#{s.name}'").each do |row|
|
120
|
-
return false if row[0] != s.source_id.to_s
|
120
|
+
return false if row[0].to_s != s.source_id.to_s
|
121
121
|
return false if row[1] != s.name
|
122
|
-
return false if row[2] != s.priority.to_s
|
122
|
+
return false if row[2].to_s != s.priority.to_s
|
123
123
|
return false if row[3] != s.partition_type.to_s
|
124
124
|
return false if row[4] != s.sync_type.to_s
|
125
125
|
return false if row[5] != (s.schema ? "" : get_attrib_counter(data))
|
@@ -127,6 +127,7 @@ module TestHelpers
|
|
127
127
|
return false if row[7] != s.blob_attribs
|
128
128
|
return false if row[8] != s.has_many
|
129
129
|
end
|
130
|
+
|
130
131
|
data = json_clone(data)
|
131
132
|
if s.schema
|
132
133
|
schema = JSON.parse(s.schema)
|
@@ -145,7 +146,7 @@ module TestHelpers
|
|
145
146
|
else
|
146
147
|
db.execute("select * from object_values where source_id=#{s.source_id}").each do |row|
|
147
148
|
object = data[row[2]]
|
148
|
-
return false if object.nil? or object[row[1]] != row[3] or row[0] != s.source_id.to_s
|
149
|
+
return false if object.nil? or object[row[1]] != row[3] or row[0].to_s != s.source_id.to_s
|
149
150
|
object.delete(row[1])
|
150
151
|
data.delete(row[2]) if object.empty?
|
151
152
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'rhosync'
|
2
|
+
FOO_RECORD_RESOLUTION = 2
|
3
|
+
FOO_RECORD_SIZE = 8
|
4
|
+
|
5
|
+
include Rhosync
|
6
|
+
include Rhosync::Stats
|
7
|
+
|
8
|
+
describe "Middleware" do
|
9
|
+
|
10
|
+
before(:each) do
|
11
|
+
@now = 10.0
|
12
|
+
Store.db.flushdb
|
13
|
+
app = mock('app')
|
14
|
+
app.stub!(:call)
|
15
|
+
@middleware = Middleware.new(app)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should compute http average" do
|
19
|
+
Time.stub!(:now).and_return { @now += 0.3; @now }
|
20
|
+
env = {
|
21
|
+
'rack.request.query_hash' => {
|
22
|
+
'source_id' => 'SampleAdapter'
|
23
|
+
},
|
24
|
+
'REQUEST_METHOD' => 'GET',
|
25
|
+
'REQUEST_PATH' => '/application'
|
26
|
+
}
|
27
|
+
10.times { @middleware.call(env) }
|
28
|
+
metric = 'http:GET:/application:SampleAdapter'
|
29
|
+
Record.key(metric).should == "stat:#{metric}"
|
30
|
+
Record.range(metric, 0, -1).should == ["10.0,3.0:19"]
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'rhosync'
|
2
|
+
FOO_RECORD_RESOLUTION = 2
|
3
|
+
FOO_RECORD_SIZE = 8
|
4
|
+
|
5
|
+
include Rhosync
|
6
|
+
include Rhosync::Stats
|
7
|
+
|
8
|
+
describe "Record" do
|
9
|
+
|
10
|
+
before(:each) do
|
11
|
+
@now = 9
|
12
|
+
Store.db.flushdb
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should add metric to the record and trim record size" do
|
16
|
+
Time.stub!(:now).and_return { @now += 1; @now }
|
17
|
+
10.times { Record.add('foo') }
|
18
|
+
Store.db.zrange('stat:foo', 0, -1).should == ["2:13", "2:15", "2:17", "2:19"]
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should add single record" do
|
22
|
+
Time.stub!(:now).and_return { @now += 1; @now }
|
23
|
+
Record.add('foo')
|
24
|
+
Store.db.zrange('stat:foo', 0, -1).should == ["1:10"]
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should add absolute metric value" do
|
28
|
+
Time.stub!(:now).and_return { @now += 1; @now }
|
29
|
+
time = 0
|
30
|
+
4.times do
|
31
|
+
Record.add('foo',time) do |current,value|
|
32
|
+
Record.save_average(current, value)
|
33
|
+
end
|
34
|
+
time += 1
|
35
|
+
end
|
36
|
+
Store.db.zrange('stat:foo', 0, -1).should == ["2.0,1.0:11", "2.0,5.0:13"]
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should update metric" do
|
40
|
+
Rhosync.stats = true
|
41
|
+
Time.stub!(:now).and_return { @now += 1; @now }
|
42
|
+
4.times do
|
43
|
+
Record.update('foo') do
|
44
|
+
# something interesting
|
45
|
+
end
|
46
|
+
end
|
47
|
+
Store.db.zrange('stat:foo', 0, -1).should == ["1,1.0:15", "1,1.0:18", "1,1.0:21"]
|
48
|
+
Rhosync.stats = nil
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should get range of metric values" do
|
52
|
+
Time.stub!(:now).and_return { @now += 1; @now }
|
53
|
+
10.times { Record.add('foo') }
|
54
|
+
Record.range('foo', 0, 1).should == ["2:13", "2:15"]
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should reset metric" do
|
58
|
+
Time.stub!(:now).and_return { @now += 1; @now }
|
59
|
+
10.times { Record.add('foo') }
|
60
|
+
Store.db.zrange('stat:foo', 0, -1).should == ["2:13", "2:15", "2:17", "2:19"]
|
61
|
+
Record.reset('foo')
|
62
|
+
Store.db.zrange('stat:foo', 0, -1).should == []
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should reset all metrics" do
|
66
|
+
Record.add('foo')
|
67
|
+
Record.add('bar')
|
68
|
+
Record.reset_all
|
69
|
+
Store.db.keys('stat:*').should == []
|
70
|
+
end
|
71
|
+
end
|