rhosync 2.0.8 → 2.0.9
Sign up to get free protection for your applications and to get access to all the features.
- 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
|