rhoconnect 3.1.2 → 3.2.0.beta1

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.
Files changed (248) hide show
  1. data/CHANGELOG.md +14 -2
  2. data/CREDITS +151 -10
  3. data/Gemfile +16 -5
  4. data/Gemfile.lock +58 -23
  5. data/Rakefile +70 -50
  6. data/bench/bench_runner.rb +2 -2
  7. data/bench/benchapp/Gemfile +6 -0
  8. data/bench/benchapp/Gemfile.lock +5 -0
  9. data/bench/benchapp/config.ru +2 -0
  10. data/bench/lib/bench/cli.rb +2 -0
  11. data/bench/lib/bench/distr_runner.rb +3 -2
  12. data/bench/lib/bench/runner.rb +1 -1
  13. data/bench/lib/bench.rb +10 -1
  14. data/bench/run_bench.sh +1 -1
  15. data/bench/scripts/test_query_script.rb +2 -1
  16. data/bench/spec/bench_spec_helper.rb +1 -0
  17. data/bin/rhoconnect +9 -27
  18. data/bin/rhoconnect-benchmark +10 -1
  19. data/commands/commands/dtach_commands/dtach_about.rb +6 -0
  20. data/commands/commands/dtach_commands/dtach_install.rb +30 -0
  21. data/commands/commands/redis_commands/redis_about.rb +6 -0
  22. data/commands/commands/redis_commands/redis_attach.rb +6 -0
  23. data/commands/commands/redis_commands/redis_download.rb +33 -0
  24. data/commands/commands/redis_commands/redis_install.rb +26 -0
  25. data/commands/commands/redis_commands/redis_make.rb +9 -0
  26. data/commands/commands/redis_commands/redis_restart.rb +7 -0
  27. data/commands/commands/redis_commands/redis_runner.rb +67 -0
  28. data/commands/commands/redis_commands/redis_start.rb +6 -0
  29. data/commands/commands/redis_commands/redis_startbg.rb +6 -0
  30. data/commands/commands/redis_commands/redis_stop.rb +6 -0
  31. data/commands/commands/rhoconnect/attach.rb +7 -0
  32. data/commands/commands/rhoconnect/clean_start.rb +9 -0
  33. data/commands/commands/rhoconnect/config.rb +15 -0
  34. data/commands/commands/rhoconnect/console.rb +15 -0
  35. data/commands/commands/rhoconnect/console_helper.rb +3 -0
  36. data/commands/commands/rhoconnect/create_user.rb +18 -0
  37. data/commands/commands/rhoconnect/delete_device.rb +9 -0
  38. data/commands/commands/rhoconnect/delete_user.rb +8 -0
  39. data/commands/commands/rhoconnect/flushdb.rb +14 -0
  40. data/commands/commands/rhoconnect/get_token.rb +25 -0
  41. data/commands/commands/rhoconnect/reset.rb +16 -0
  42. data/commands/commands/rhoconnect/reset_refresh.rb +11 -0
  43. data/commands/commands/rhoconnect/restart.rb +7 -0
  44. data/commands/commands/rhoconnect/secret.rb +11 -0
  45. data/commands/commands/rhoconnect/set_admin_password.rb +26 -0
  46. data/commands/commands/rhoconnect/spec.rb +15 -0
  47. data/commands/commands/rhoconnect/start.rb +18 -0
  48. data/commands/commands/rhoconnect/startbg.rb +34 -0
  49. data/commands/commands/rhoconnect/startdebug.rb +35 -0
  50. data/commands/commands/rhoconnect/stop.rb +11 -0
  51. data/commands/commands/rhoconnect/war.rb +32 -0
  52. data/commands/commands/rhoconnect/web.rb +7 -0
  53. data/commands/execute.rb +35 -0
  54. data/commands/generators/app.rb +6 -0
  55. data/commands/generators/source.rb +6 -0
  56. data/commands/utilities/dtach_installed.rb +10 -0
  57. data/doc/benchmarks-running.txt +5 -0
  58. data/doc/command-line.txt +216 -27
  59. data/doc/heroku-addon.txt +1 -1
  60. data/doc/preparing-production.txt +20 -1
  61. data/doc/public/cli.txt +191 -0
  62. data/doc/push-backend-setup.txt +148 -0
  63. data/doc/push-client-setup.txt +61 -0
  64. data/doc/push-server-setup.txt +91 -0
  65. data/doc/push.txt +8 -137
  66. data/doc/rest-api.txt +96 -0
  67. data/doc/settings.txt +1 -1
  68. data/doc/supported-platforms.txt +2 -1
  69. data/doc/tutorial.txt +6 -4
  70. data/examples/simple/Gemfile +39 -0
  71. data/examples/simple/Rakefile +7 -12
  72. data/examples/simple/config.ru +16 -31
  73. data/examples/simple/settings/settings.yml +5 -4
  74. data/examples/simple/sources/product.rb +51 -0
  75. data/generators/templates/application/Gemfile +7 -0
  76. data/generators/templates/application/Rakefile +5 -18
  77. data/generators/templates/application/config.ru +11 -19
  78. data/install.sh +24 -49
  79. data/installer/unix-like/create_texts.rb +71 -123
  80. data/installer/unix-like/post_install.sh +3 -0
  81. data/installer/unix-like/post_uninstall.sh +2 -0
  82. data/installer/unix-like/pre_install.sh +5 -3
  83. data/installer/unix-like/pre_uninstall.sh +14 -6
  84. data/installer/unix-like/rho_connect_install_checkers.rb +1 -1
  85. data/installer/unix-like/rho_connect_install_constants.rb +6 -10
  86. data/installer/unix-like/rho_connect_install_debian.rb +2 -2
  87. data/installer/unix-like/rho_connect_install_dnd.rb +2 -5
  88. data/installer/unix-like/rho_connect_install_installers.rb +15 -23
  89. data/installer/unix-like/rho_connect_install_yum.rb +2 -2
  90. data/installer/utils/constants.rb +4 -4
  91. data/installer/utils/create_sha1.rb +1 -1
  92. data/installer/utils/nix_install_test.rb +32 -31
  93. data/installer/utils/nix_installation.rake +1 -1
  94. data/installer/utils/package_upload/repos.rake +34 -30
  95. data/installer/utils/package_upload/s3_upload.rb +3 -3
  96. data/lib/rhoconnect/api/source/fast_delete.rb +10 -0
  97. data/lib/rhoconnect/api/source/fast_insert.rb +10 -0
  98. data/lib/rhoconnect/api/source/fast_update.rb +10 -0
  99. data/lib/rhoconnect/api/source/get_source_params.rb +1 -1
  100. data/lib/rhoconnect/api/source/list_sources.rb +2 -2
  101. data/lib/rhoconnect/api/source/save_adapter.rb +1 -1
  102. data/lib/rhoconnect/api/source/update_source_params.rb +6 -0
  103. data/lib/rhoconnect/async.rb +82 -0
  104. data/lib/rhoconnect/bulk_data/bulk_data.rb +5 -1
  105. data/lib/rhoconnect/client_sync.rb +18 -3
  106. data/lib/rhoconnect/console/rhoconnect_api.rb +2 -2
  107. data/lib/rhoconnect/console/server.rb +5 -32
  108. data/lib/rhoconnect/console.rb +2 -2
  109. data/lib/rhoconnect/graph_helper.rb +225 -0
  110. data/lib/rhoconnect/jobs/bulk_data_job.rb +24 -2
  111. data/lib/rhoconnect/server.rb +31 -11
  112. data/lib/rhoconnect/source.rb +10 -5
  113. data/lib/rhoconnect/source_sync.rb +32 -2
  114. data/lib/rhoconnect/tasks.rb +19 -108
  115. data/lib/rhoconnect/test_methods.rb +20 -0
  116. data/lib/rhoconnect/utilities.rb +118 -0
  117. data/lib/rhoconnect/version.rb +1 -1
  118. data/lib/rhoconnect/web-console/controllers/admins.js +245 -0
  119. data/lib/rhoconnect/web-console/models/adapter.js +53 -0
  120. data/lib/rhoconnect/web-console/models/client.js +105 -0
  121. data/lib/rhoconnect/web-console/models/doc.js +113 -0
  122. data/lib/rhoconnect/web-console/models/session.js +40 -0
  123. data/lib/rhoconnect/web-console/models/source.js +115 -0
  124. data/lib/rhoconnect/web-console/models/stats.js +84 -0
  125. data/lib/rhoconnect/web-console/models/user.js +111 -0
  126. data/lib/rhoconnect/web-console/public/backbone.js +1432 -0
  127. data/lib/rhoconnect/web-console/public/bootstrap.css +3990 -0
  128. data/lib/rhoconnect/{console/app → web-console}/public/jqplot/excanvas.min.js +0 -0
  129. data/lib/rhoconnect/{console/app → web-console}/public/jqplot/jqplot.barRenderer.min.js +0 -0
  130. data/lib/rhoconnect/{console/app → web-console}/public/jqplot/jqplot.canvasAxisLabelRenderer.js +0 -0
  131. data/lib/rhoconnect/{console/app → web-console}/public/jqplot/jqplot.canvasAxisTickRenderer.js +0 -0
  132. data/lib/rhoconnect/{console/app → web-console}/public/jqplot/jqplot.canvasTextRenderer.js +0 -0
  133. data/lib/rhoconnect/{console/app → web-console}/public/jqplot/jqplot.categoryAxisRenderer.min.js +0 -0
  134. data/lib/rhoconnect/{console/app → web-console}/public/jqplot/jqplot.cursor.js +0 -0
  135. data/lib/rhoconnect/{console/app → web-console}/public/jqplot/jqplot.dateAxisRenderer.js +0 -0
  136. data/lib/rhoconnect/{console/app → web-console}/public/jqplot/jqplot.dateAxisRenderer.min.js +0 -0
  137. data/lib/rhoconnect/{console/app → web-console}/public/jqplot/jqplot.pointLabels.min.js +0 -0
  138. data/lib/rhoconnect/{console/app → web-console}/public/jqplot/jquery-1.4.2.min.js +0 -0
  139. data/lib/rhoconnect/{console/app → web-console}/public/jqplot/jquery.jqplot.min.css +0 -0
  140. data/lib/rhoconnect/{console/app → web-console}/public/jqplot/jquery.jqplot.min.js +0 -0
  141. data/lib/rhoconnect/web-console/public/jquery-1.7.1.min.js +154 -0
  142. data/lib/rhoconnect/web-console/public/rhoconnect-web.js +15 -0
  143. data/lib/rhoconnect/web-console/public/underscore.js +999 -0
  144. data/lib/rhoconnect/web-console/server.rb +55 -0
  145. data/lib/rhoconnect/web-console/templates/index.erb +90 -0
  146. data/lib/rhoconnect/web-console/templates/jqplot.erb +60 -0
  147. data/lib/rhoconnect/web-console/views/api_token.js +16 -0
  148. data/lib/rhoconnect/web-console/views/doc.js +63 -0
  149. data/lib/rhoconnect/web-console/views/edit_user.js +43 -0
  150. data/lib/rhoconnect/web-console/views/home.js +56 -0
  151. data/lib/rhoconnect/web-console/views/index.js +63 -0
  152. data/lib/rhoconnect/web-console/views/new_ping.js +58 -0
  153. data/lib/rhoconnect/web-console/views/new_user.js +29 -0
  154. data/lib/rhoconnect/web-console/views/server_doc.js +103 -0
  155. data/lib/rhoconnect/web-console/views/set_adapter.js +38 -0
  156. data/lib/rhoconnect/web-console/views/settings.js +53 -0
  157. data/lib/rhoconnect/web-console/views/show_device.js +56 -0
  158. data/lib/rhoconnect/web-console/views/show_user.js +38 -0
  159. data/lib/rhoconnect/web-console/views/source_docs.js +30 -0
  160. data/lib/rhoconnect/web-console/views/stats.js +69 -0
  161. data/lib/rhoconnect/web-console/views/users.js +20 -0
  162. data/lib/rhoconnect.rb +2 -1
  163. data/rhoconnect.gemspec +3 -1
  164. data/spec/api/application/rhoconnect_api_spec.rb +3 -5
  165. data/spec/api/source/fast_delete_spec.rb +27 -0
  166. data/spec/api/source/fast_insert_spec.rb +28 -0
  167. data/spec/api/source/fast_update_spec.rb +51 -0
  168. data/spec/api/source/get_source_params_spec.rb +1 -0
  169. data/spec/api/source/update_source_params_spec.rb +24 -0
  170. data/spec/async_spec.rb +19 -0
  171. data/spec/client_sync_spec.rb +19 -2
  172. data/spec/javascripts/PlayerSpec.js +58 -0
  173. data/spec/javascripts/admins_routes_spec.js +117 -0
  174. data/spec/javascripts/admins_spec.js +27 -0
  175. data/spec/javascripts/doc_view_spec.js +37 -0
  176. data/spec/javascripts/edit_user_view_spec.js +44 -0
  177. data/spec/javascripts/helpers/SpecHelper.js +9 -0
  178. data/spec/javascripts/helpers/jasmine-jquery.js +305 -0
  179. data/spec/javascripts/helpers/jasmine-sinon.js +43 -0
  180. data/spec/javascripts/helpers/sinon-1.3.2.js +3551 -0
  181. data/spec/javascripts/home_view_spec.js +39 -0
  182. data/spec/javascripts/index_view_spec.js +42 -0
  183. data/spec/javascripts/new_ping_view_spec.js +48 -0
  184. data/spec/javascripts/new_user_view_spec.js +42 -0
  185. data/spec/javascripts/server_doc_view_spec.js +39 -0
  186. data/spec/javascripts/set_adapter_view_spec.js +32 -0
  187. data/spec/javascripts/show_device_view_spec.js +41 -0
  188. data/spec/javascripts/show_user_view_spec.js +46 -0
  189. data/spec/javascripts/source_docs_view_spec.js +36 -0
  190. data/spec/javascripts/support/jasmine.yml +79 -0
  191. data/spec/javascripts/support/jasmine_config.rb +23 -0
  192. data/spec/javascripts/support/jasmine_runner.rb +32 -0
  193. data/spec/javascripts/users_view_spec.js +35 -0
  194. data/spec/jobs/bulk_data_job_spec.rb +10 -2
  195. data/spec/perf/bulk_data_perf_spec.rb +1 -0
  196. data/spec/server/server_spec.rb +3 -1
  197. data/spec/source_sync_spec.rb +14 -1
  198. data/spec/spec_helper.rb +51 -0
  199. data/spec/store_spec.rb +6 -0
  200. data/spec/test_methods_spec.rb +11 -0
  201. data/tasks/redis.rake +3 -1
  202. metadata +172 -64
  203. data/doc/contributing.txt +0 -60
  204. data/lib/rhoconnect/console/app/helpers/auth_helper.rb +0 -22
  205. data/lib/rhoconnect/console/app/helpers/extensions.rb +0 -19
  206. data/lib/rhoconnect/console/app/helpers/helpers.rb +0 -57
  207. data/lib/rhoconnect/console/app/public/ThickBox.css +0 -649
  208. data/lib/rhoconnect/console/app/public/home.css +0 -431
  209. data/lib/rhoconnect/console/app/public/images/foot_logo_rhoconnect.png +0 -0
  210. data/lib/rhoconnect/console/app/public/images/header_halo.jpg +0 -0
  211. data/lib/rhoconnect/console/app/public/images/land_separator.gif +0 -0
  212. data/lib/rhoconnect/console/app/public/images/landing_header.jpg +0 -0
  213. data/lib/rhoconnect/console/app/public/images/logo_rhoconnect.png +0 -0
  214. data/lib/rhoconnect/console/app/public/images/tabs_separator.png +0 -0
  215. data/lib/rhoconnect/console/app/public/main.css +0 -7
  216. data/lib/rhoconnect/console/app/public/reset.css +0 -76
  217. data/lib/rhoconnect/console/app/public/style.css +0 -2201
  218. data/lib/rhoconnect/console/app/public/text.txt +0 -0
  219. data/lib/rhoconnect/console/app/routes/adapter.rb +0 -28
  220. data/lib/rhoconnect/console/app/routes/auth.rb +0 -29
  221. data/lib/rhoconnect/console/app/routes/client.rb +0 -31
  222. data/lib/rhoconnect/console/app/routes/docs.rb +0 -145
  223. data/lib/rhoconnect/console/app/routes/heroku.rb +0 -19
  224. data/lib/rhoconnect/console/app/routes/home.rb +0 -63
  225. data/lib/rhoconnect/console/app/routes/timing.rb +0 -242
  226. data/lib/rhoconnect/console/app/routes/user.rb +0 -122
  227. data/lib/rhoconnect/console/app/views/adapter.erb +0 -16
  228. data/lib/rhoconnect/console/app/views/client.erb +0 -30
  229. data/lib/rhoconnect/console/app/views/content.erb +0 -14
  230. data/lib/rhoconnect/console/app/views/doc.erb +0 -8
  231. data/lib/rhoconnect/console/app/views/docdata.erb +0 -28
  232. data/lib/rhoconnect/console/app/views/docs.erb +0 -30
  233. data/lib/rhoconnect/console/app/views/edituser.erb +0 -13
  234. data/lib/rhoconnect/console/app/views/headermenu.erb +0 -40
  235. data/lib/rhoconnect/console/app/views/home.erb +0 -24
  236. data/lib/rhoconnect/console/app/views/index.erb +0 -58
  237. data/lib/rhoconnect/console/app/views/jqplot.erb +0 -52
  238. data/lib/rhoconnect/console/app/views/layout.erb +0 -153
  239. data/lib/rhoconnect/console/app/views/login.erb +0 -26
  240. data/lib/rhoconnect/console/app/views/newuser.erb +0 -17
  241. data/lib/rhoconnect/console/app/views/ping.erb +0 -40
  242. data/lib/rhoconnect/console/app/views/result.erb +0 -11
  243. data/lib/rhoconnect/console/app/views/rightboxlinks.erb +0 -15
  244. data/lib/rhoconnect/console/app/views/select_doc.erb +0 -17
  245. data/lib/rhoconnect/console/app/views/upload_doc.erb +0 -23
  246. data/lib/rhoconnect/console/app/views/user.erb +0 -29
  247. data/lib/rhoconnect/console/app/views/users.erb +0 -19
  248. data/lib/rhoconnect/server/views/index.erb +0 -13
@@ -0,0 +1,38 @@
1
+ App.Views.SetAdapter = Backbone.View.extend({
2
+
3
+ events: {
4
+ "submit form" : "set_adapter"
5
+ },
6
+
7
+ initialize: function() {
8
+ this.render("",domain);
9
+ this.model.get_adapter();
10
+ },
11
+
12
+ set_adapter: function(e){
13
+ e.preventDefault();
14
+ var adapter_url = $('#input_adapter').val();
15
+ var domain = $('input#domain').val();
16
+ this.render(adapter_url,domain);
17
+ $(".setadapter-status")[0].firstChild.className = "label label-warning";
18
+ $(".setadapter-status")[0].firstChild.innerHTML = "loading...";
19
+ $(".setadapter-status").css("visibility","visible");
20
+ this.delegateEvents();
21
+ this.model.set_adapter(adapter_url, self);
22
+ },
23
+
24
+ render: function(adapter_url,domain) {
25
+ $('#secondary-nav').css('display','block');
26
+ out = "<h3>Backend App URL</h3>";
27
+ out += "<form style='margin:0'>";
28
+ out += "<input id='input_adapter' type='text' name='adapter_url' value='"+adapter_url+"' class='input-xlarge' placeholder='Enter Adapter URL' style='margin:0'/>";
29
+ out += "<input type='submit' value='Submit' class='btn btn-primary' style='margin-left:10px'/><div class='setadapter-status' style='display:inline;margin-left:10px;visibility:hidden'><span class=''></span></div>";
30
+ out += "</form>";
31
+
32
+ $(this.el).html(out);
33
+ $('#settings_main').html(this.el);
34
+ }
35
+ });
36
+
37
+
38
+
@@ -0,0 +1,53 @@
1
+ App.Views.Settings = Backbone.View.extend({
2
+
3
+ events: {
4
+ "click a#change_admin" : "change_admin",
5
+ "click a#api_token" : "api_token",
6
+ "click a#backend_app" : "backend_app"
7
+ },
8
+
9
+ initialize: function() {
10
+ this.render();
11
+ new App.Views.EditUser()
12
+ },
13
+
14
+ change_admin: function(){
15
+ this.change_tab('change_admin')
16
+ new App.Views.EditUser()
17
+ },
18
+
19
+ api_token: function(){
20
+ this.change_tab('api_token')
21
+ new App.Views.ApiToken()
22
+ },
23
+
24
+ backend_app: function(){
25
+ this.change_tab('backend_app')
26
+ adapter = new Adapter();
27
+ new App.Views.SetAdapter({model: adapter })
28
+ },
29
+
30
+ change_tab: function(tab){
31
+ $('#change_admin').parent().attr('class','');
32
+ $('#api_token').parent().attr('class','');
33
+ $('#backend_app').parent().attr('class','');
34
+ $('#'+tab).parent().attr('class','active');
35
+ },
36
+
37
+ render: function() {
38
+ $('#secondary-nav').css('display','block');
39
+ out = "<div id='settings-alert' class='alert alert-error' style='display:none'></div>"
40
+ out += "<div class='tabs-left'><ul class='nav nav-tabs'>"
41
+ out += "<li class='active'><a id='change_admin'>Change Admin Password</a></li>"
42
+ out += "<li><a id='api_token'>API Token</a></li>"
43
+ out += "<li><a id='backend_app'>Plugin Settings</a></li>"
44
+ out += "</ul>"
45
+ out += "<div id='settings_main'>"
46
+ out += "</div>"
47
+ out += "</div></div>"
48
+
49
+ $(this.el).html(out);
50
+ $('#main_content').html(this.el);
51
+ return this
52
+ }
53
+ });
@@ -0,0 +1,56 @@
1
+ App.Views.ShowDevice = Backbone.View.extend({
2
+
3
+ events: {
4
+ "click a#delete-device" : "delete_device",
5
+ },
6
+
7
+ initialize: function() {
8
+ var device_id = this.model.get('device_id');
9
+ this.render(device_id);
10
+ this.model.get_client_params(device_id);
11
+ //this.model.list_client_docs(device_id,'Product');
12
+ source = new Source();
13
+ source.set('partition_type','user');
14
+ source.set('user_id',this.model.get('user_id'));
15
+ source.set('client_id',device_id);
16
+ source.set('doctype','client');
17
+ source.fetch();
18
+ },
19
+
20
+ delete_device: function() {
21
+ if(confirm("Are you sure you want to delete this device?")){
22
+ var user_id = this.model.get('user_id');
23
+ var client_id = this.model.get('device_id');
24
+ $.ajax({
25
+ type: 'POST',
26
+ url: ' /api/client/delete_client',
27
+ data: {api_token : this.model.get('api_token'), user_id : user_id, client_id : client_id},
28
+ success: function(resp){
29
+ router.navigate("user/"+user_id,true)
30
+ },
31
+ error: function(resp){
32
+ if(resp.status == 422){
33
+ new App.Views.Index()
34
+ }
35
+ $('#showdevice-alert')[0].innerHTML = resp.responseText;
36
+ $('#showdevice-alert').css('display','block');
37
+ }
38
+ })
39
+ }
40
+ },
41
+
42
+ render: function(device_id) {
43
+ $('#secondary-nav').css('display','block');
44
+ out = "<div class='page-header well'><span style='font-size:24px;line-height:36px;font-weight:bold'>Device: "+device_id+"</span>";
45
+ out += "<span class='pull-right'><a id='delete-device' class='btn btn-danger'>Delete Device</a></span></div>";
46
+ out += "<div id='showdevice-alert' class='alert alert-error' style='display:none'></div>";
47
+ out += "<table id='deviceattr-table' class='table table-bordered'>";
48
+ out += "<tr><th><h3>Attributes</h3></th></tr>";
49
+ out += "</table>";
50
+ out += "<table id='source-table' class='table table-bordered'><tr><th><h3>Sources for device</h3></th></tr>";
51
+ out += "</table>"
52
+
53
+ $(this.el).html(out);
54
+ $('#main_content').html(this.el);
55
+ }
56
+ });
@@ -0,0 +1,38 @@
1
+ App.Views.ShowUser = Backbone.View.extend({
2
+
3
+ events: {
4
+ "click a#delete-user" : "delete_user",
5
+ },
6
+
7
+ initialize: function() {
8
+ var name = this.model.get('name');
9
+ this.render(name);
10
+ client = new Client();
11
+ client.get_clients(name);
12
+ source = new Source();
13
+ source.set('partition_type','user');
14
+ source.set('user_id',name);
15
+ source.set('doctype','source');
16
+ source.fetch();
17
+ },
18
+
19
+ delete_user: function(e) {
20
+ e.preventDefault();
21
+ this.model.delete_user();
22
+ },
23
+
24
+ render: function(name) {
25
+ $('#secondary-nav').css('display','block');
26
+ out = "<div class='page-header well'><div style='font-size:24px;font-weight:bold;display:inline'>User: "+name+"</div><div class='pull-right' style='display:inline'>";
27
+ out += "<a id='delete-user' class='btn btn-danger'>Delete User</a><a href='#user/newping/"+name+"' class='btn' style='margin-left:10px'>Ping User</a></div></div>";
28
+ out += "<div id='showuser-alert' class='alert alert-error' style='display:none'></div>";
29
+ out += "<table id='source-table' class='table table-bordered'>";
30
+ out += "<tr><th><h3>Sources</h3></th></tr>";
31
+ out += "</table>";
32
+ out += "<table id='device-table' class='table table-bordered'><tr><th><h3>Registered Devices</h3></th></tr>";
33
+ out += "</table>"
34
+
35
+ $(this.el).html(out);
36
+ $('#main_content').html(this.el);
37
+ }
38
+ });
@@ -0,0 +1,30 @@
1
+ App.Views.SourceDocs = Backbone.View.extend({
2
+
3
+ initialize: function() {
4
+ var source_id = this.model.get('source_id');
5
+ var user = this.model.get('user_id');
6
+ var doctype = this.model.get('doctype');
7
+ var client_id = this.model.get('client_id');
8
+ this.render(source_id);
9
+ this.model.get_source_params(source_id);
10
+ if(doctype == 'client'){
11
+ client = new Client();
12
+ client.list_client_docs(client_id,source_id)
13
+ }
14
+ else{
15
+ this.model.list_source_docs(source_id,user);
16
+ }
17
+ },
18
+
19
+ render: function(source_id) {
20
+ $('#secondary-nav').css('display','block');
21
+ out = "<div class='page-header well'><h1>"+source_id+"</h1></div>";
22
+ out += "<div class='docalert alert-error' style='display:none'></div>";
23
+ out += "<table id='sourceparams-table' class='table table-bordered'><thead><tr><th><h3>Attributes</h3></th></tr></thead>";
24
+ out += "</table>";
25
+ out += "<table id='sourcedocs-table' class='table table-bordered'><tr><th class='span5'><h3>Documents</h3></th></tr>";
26
+ out += "</table>";
27
+ $(this.el).html(out);
28
+ $('#main_content').html(this.el);
29
+ }
30
+ });
@@ -0,0 +1,69 @@
1
+ App.Views.Stats = Backbone.View.extend({
2
+
3
+ events: {
4
+ "click a#user_count" : "user_count",
5
+ "click a#device_count" : "device_count",
6
+ "click a#http_timing" : "http_timing",
7
+ "click a#source_timing" : "source_timing",
8
+ "click a#source_timing_display" : "source_timing_display",
9
+
10
+ },
11
+
12
+ initialize: function(){
13
+ this.render();
14
+ this.user_count();
15
+ },
16
+
17
+ user_count: function(){
18
+ this.change_tab('user_count');
19
+ this.model.user_stats();
20
+ },
21
+
22
+ device_count: function(){
23
+ this.change_tab('device_count');
24
+ this.model.device_count();
25
+ },
26
+
27
+ http_timing: function(ev){
28
+ var display_name = ev.currentTarget.innerHTML;
29
+ this.change_tab('http_timing');
30
+ this.model.http_timing(display_name);
31
+ },
32
+
33
+ source_timing: function(){
34
+ this.change_tab('source_timing');
35
+ this.model.source_timing();
36
+ },
37
+
38
+ source_timing_display: function(ev){
39
+ var display_name = ev.currentTarget.innerHTML;
40
+ this.change_tab('source_timing');
41
+ this.model.source_timing(display_name);
42
+ },
43
+
44
+ change_tab: function(tab){
45
+ $('#user_count').parent().attr('class','');
46
+ $('#device_count').parent().attr('class','');
47
+ $('#http_timing').parent().attr('class','');
48
+ $('#source_timing').parent().attr('class','');
49
+ $('#'+tab).parent().attr('class','active');
50
+ },
51
+
52
+ render: function(){
53
+ $('#secondary-nav').css('display','block');
54
+ out = "<div id='stats-alert' class='alert alert-error' style='display:none'></div>"
55
+ out += "<div class='tabs-left'><ul class='nav nav-tabs'>"
56
+ out += "<li class='active'><a id='user_count'>User Count</a></li>"
57
+ out += "<li><a id='device_count'>Device Count</a></li>"
58
+ out += "<li><a id='http_timing'>HTTP Timing</a></li>"
59
+ out += "<li><a id='source_timing'>Source Timing</a></li>"
60
+ out += "</ul>"
61
+ out += "<div id='stats_main' style='margin-left:200px'>"
62
+ out += "</div>"
63
+ //out += "<ul id='source-list' class='nav nav-pills' style='margin-left:200px'></ul>"
64
+ out += "</div></div>"
65
+
66
+ $(this.el).html(out);
67
+ $('#main_content').html(this.el);
68
+ }
69
+ })
@@ -0,0 +1,20 @@
1
+ App.Views.Users = Backbone.View.extend({
2
+
3
+
4
+ initialize: function() {
5
+ this.render();
6
+ this.model.get_users('user_table');
7
+ },
8
+
9
+ render: function() {
10
+ $('#secondary-nav').css('display','block');
11
+ out = "<div id='ping-alert' class='alert alert-error' style='display:none'></div>";
12
+ out += "<table id='users_table' class='table table-bordered'>";
13
+ out += "<tr><th><div style='display:inline;font-size:18px'>Registered Users<div class='pull-right'><a href='#users/new' class='btn btn-primary'>Create User</a>";
14
+ out += "<a href='#users/newping' class='btn btn-primary' style='margin-left:10px'>Ping Users</a></div></th></tr>";
15
+ out += "</table></form>";
16
+
17
+ $(this.el).html(out);
18
+ $('#main_content').html(this.el);
19
+ }
20
+ });
data/lib/rhoconnect.rb CHANGED
@@ -56,7 +56,7 @@ module Rhoconnect
56
56
  #Load environment
57
57
  environment = (ENV['RHO_ENV'] || ENV['RACK_ENV'] || :development).to_sym
58
58
  # Initialize Rhoconnect and Resque
59
- Rhoconnect.base_directory = basedir
59
+ Rhoconnect.base_directory = basedir
60
60
  Rhoconnect.app_directory = get_setting(config,environment,:app_directory)
61
61
  Rhoconnect.data_directory = get_setting(config,environment,:data_directory)
62
62
  Rhoconnect.vendor_directory = get_setting(config,environment,:vendor_directory)
@@ -143,6 +143,7 @@ module Rhoconnect
143
143
  source_config = sources[source_name] unless (sources.nil? or sources[source_name].nil?)
144
144
  env_config = Rhoconnect.get_config(Rhoconnect.base_directory)[Rhoconnect.environment]
145
145
  force_default = source_config[:force_default]
146
+ source_config.delete(:force_default)
146
147
  # apply global env settings
147
148
  [:poll_interval].each do |setting|
148
149
  def_setting = env_config["#{setting.to_s}_default".to_sym]
data/rhoconnect.gemspec CHANGED
@@ -19,6 +19,7 @@ Gem::Specification.new do |s|
19
19
  CHANGELOG.md CREDITS Gemfile Gemfile.lock install.sh README.md Rakefile LICENSE Rakefile rhoconnect.gemspec
20
20
  )
21
21
  s.files += Dir.glob("bench/**/*")
22
+ s.files += Dir.glob("commands/**/*")
22
23
  s.files += Dir.glob("doc/**/*")
23
24
  s.files += Dir.glob("examples/**/*")
24
25
  s.files += Dir.glob("generators/**/*")
@@ -46,5 +47,6 @@ Gem::Specification.new do |s|
46
47
  s.add_dependency('redis', '>= 2.2.0')
47
48
  s.add_dependency('resque', '~> 1.20.0')
48
49
  s.add_dependency('rest-client', '~> 1.6.1')
49
- s.add_dependency('templater', '~> 1.0.0')
50
+ s.add_dependency('templater', '~> 1.0.0')
51
+ s.add_dependency('thor', '~> 0.14.6')
50
52
  end
@@ -24,11 +24,6 @@ describe "RhoconnectApi" do
24
24
  RestClient.should_receive(:post).once
25
25
  RhoconnectApi::get_adapter('some_url',@api_token).should == ["http://test.com"]
26
26
  end
27
-
28
- it "should save adapter using direct api call" do
29
- RhoconnectApi::save_adapter('',@api_token,'http://test.com')
30
- Rhoconnect.appserver.should == 'http://test.com'
31
- end
32
27
 
33
28
  it "should save adapter using rest call" do
34
29
  RestClient.stub(:post).and_return("adpater url saved")
@@ -174,6 +169,7 @@ describe "RhoconnectApi" do
174
169
  {"name"=>"callback_url", "value"=>nil, "type"=>"string"},
175
170
  {"name"=>"poll_interval", "value"=>300, "type"=>"integer"},
176
171
  {"name"=>"retry_limit", "value"=>0, "type"=>"integer"},
172
+ {"name"=>"simulate_time", "value"=>0, "type"=>"integer"},
177
173
  {"name"=>"partition_type", "value"=>"user", "type"=>"string"},
178
174
  {"name"=>"sync_type", "value"=>"incremental", "type"=>"string"},
179
175
  {"name"=>"belongs_to", "type"=>"string", "value"=>nil},
@@ -378,6 +374,7 @@ describe "RhoconnectApi" do
378
374
  {"name"=>"callback_url", "value"=>nil, "type"=>"string"},
379
375
  {"name"=>"poll_interval", "value"=>300, "type"=>"integer"},
380
376
  {"name"=>"retry_limit", "type"=>"integer", "value"=>0},
377
+ {"name"=>"simulate_time", "value"=>0, "type"=>"integer"},
381
378
  {"name"=>"partition_type", "value"=>"user", "type"=>"string"},
382
379
  {"name"=>"sync_type", "value"=>"incremental", "type"=>"string"},
383
380
  {"name"=>"belongs_to", "type"=>"string", "value"=>nil},
@@ -403,6 +400,7 @@ describe "RhoconnectApi" do
403
400
  {"name"=>"callback_url", "value"=>nil, "type"=>"string"},
404
401
  {"name"=>"poll_interval", "value"=>201, "type"=>"integer"},
405
402
  {"name"=>"retry_limit", "value"=>0, "type"=>"integer"},
403
+ {"name"=>"simulate_time", "value"=>0, "type"=>"integer"},
406
404
  {"name"=>"partition_type", "value"=>"app", "type"=>"string"},
407
405
  {"name"=>"sync_type", "value"=>"incremental", "type"=>"string"},
408
406
  {"name"=>"belongs_to", "type"=>"string", "value"=>nil},
@@ -0,0 +1,27 @@
1
+ require File.join(File.dirname(__FILE__),'..','api_helper')
2
+
3
+ describe "RhoconnectApiFastDelete" do
4
+ it_should_behave_like "ApiHelper" do
5
+ it "should delete an object from rhoconnect's :md" do
6
+ data = {'1' => @product1, '2' => @product2, '3' => @product3}
7
+ @s = Source.load(@s_fields[:name],@s_params)
8
+ set_state(@s.docname(:md) => data,@s.docname(:md_size) => '3')
9
+ post "/api/source/fast_delete", :api_token => @api_token,
10
+ :user_id => @u.id, :source_id => @s_fields[:name], :data => {'3' => @product3}
11
+ last_response.should be_ok
12
+ data.delete('3')
13
+ verify_result(@s.docname(:md) => data,@s.docname(:md_size)=>'2')
14
+ end
15
+
16
+ it "should not properly delete the object if fast_delete is called without all the attributes (because fast_delete doesn't ensure any data integrity)" do
17
+ data = {'1' => @product1, '2' => @product2, '3' => @product3}
18
+ delete_data = {'3' => {'price' => '1.99'}}
19
+ @s = Source.load(@s_fields[:name],@s_params)
20
+ set_state(@s.docname(:md) => data,@s.docname(:md_size) => '3')
21
+ post "/api/source/fast_delete", :api_token => @api_token,
22
+ :user_id => @u.id, :source_id => @s_fields[:name], :data => delete_data
23
+ last_response.should be_ok
24
+ verify_result(@s.docname(:md) => data,@s.docname(:md_size)=>'2')
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,28 @@
1
+ require File.join(File.dirname(__FILE__),'..','api_helper')
2
+
3
+ describe "RhoconnectApiFastInsert" do
4
+ it_should_behave_like "ApiHelper" do
5
+ it "should append new objects to rhoconnect's :md" do
6
+ data = {'1' => @product1, '2' => @product2}
7
+ @s = Source.load(@s_fields[:name],@s_params)
8
+ set_state(@s.docname(:md) => data,@s.docname(:md_size) => '2')
9
+ post "/api/source/fast_insert", :api_token => @api_token,
10
+ :user_id => @u.id, :source_id => @s_fields[:name], :data => {'3' => @product3}
11
+ last_response.should be_ok
12
+ data.merge!({'3' => @product3})
13
+ verify_result(@s.docname(:md) => data,@s.docname(:md_size)=>'3')
14
+ end
15
+
16
+ it "should incorrectly append data to existing object (because fast_insert doesn't ensure any data integrity)" do
17
+ data = {'1' => @product1, '2' => @product2, '3' => @product3}
18
+ incorrect_insert = {'3' => {'price' => '1.99', 'new_field' => 'value'}}
19
+ @s = Source.load(@s_fields[:name],@s_params)
20
+ set_state(@s.docname(:md) => data,@s.docname(:md_size) => '3')
21
+ post "/api/source/fast_insert", :api_token => @api_token,
22
+ :user_id => @u.id, :source_id => @s_fields[:name], :data => incorrect_insert
23
+ last_response.should be_ok
24
+ data['3'].merge!(incorrect_insert['3'])
25
+ verify_result(@s.docname(:md) => data,@s.docname(:md_size)=>'4')
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,51 @@
1
+ require File.join(File.dirname(__FILE__),'..','api_helper')
2
+
3
+ describe "RhoconnectApiFastUpdate" do
4
+ it_should_behave_like "ApiHelper" do
5
+ it "should update an attribute and add new one for an object in rhoconnect's :md" do
6
+ data = {'1' => @product1, '2' => @product2, '3' => @product3}
7
+ @s = Source.load(@s_fields[:name],@s_params)
8
+ set_state(@s.docname(:md) => data,@s.docname(:md_size) => '3')
9
+
10
+ orig_obj_attrs = {'3' => {'price' => @product3['price']}}
11
+ new_obj_attrs = {'3' => {'price' => '0.99', 'new_attr' => 'new_value'}}
12
+
13
+ post "/api/source/fast_update", :api_token => @api_token,
14
+ :user_id => @u.id, :source_id => @s_fields[:name], :delete_data => orig_obj_attrs, :data => new_obj_attrs
15
+ last_response.should be_ok
16
+ data['3'].merge!(new_obj_attrs['3'])
17
+ verify_result(@s.docname(:md) => data,@s.docname(:md_size)=>'3')
18
+ end
19
+
20
+ it "should update one attr, add one attr, and remove one attr for an object in rhoconnect's :md" do
21
+ data = {'1' => @product1, '2' => @product2, '3' => @product3}
22
+ @s = Source.load(@s_fields[:name],@s_params)
23
+ set_state(@s.docname(:md) => data,@s.docname(:md_size) => '3')
24
+
25
+ orig_obj_attrs = {'3' => {'name' => @product3['name'], 'price' => @product3['price']}}
26
+ new_obj_attrs = {'3' => {'price' => '0.99', 'new_attr' => 'new_value'}}
27
+
28
+ post "/api/source/fast_update", :api_token => @api_token,
29
+ :user_id => @u.id, :source_id => @s_fields[:name], :delete_data => orig_obj_attrs, :data => new_obj_attrs
30
+ last_response.should be_ok
31
+ data['3'].delete('name')
32
+ data['3'].merge!(new_obj_attrs['3'])
33
+ verify_result(@s.docname(:md) => data,@s.docname(:md_size)=>'3')
34
+ end
35
+
36
+ it "should remove all attributes , but leave the count incorrect (because fast_update doesn't check if the whole object is deleted)" do
37
+ data = {'1' => @product1, '2' => @product2, '3' => @product3}
38
+ @s = Source.load(@s_fields[:name],@s_params)
39
+ set_state(@s.docname(:md) => data,@s.docname(:md_size) => '3')
40
+
41
+ orig_obj_attrs = {'3' => @product3}
42
+ new_obj_attrs = {}
43
+
44
+ post "/api/source/fast_update", :api_token => @api_token,
45
+ :user_id => @u.id, :source_id => @s_fields[:name], :delete_data => orig_obj_attrs, :data => new_obj_attrs
46
+ last_response.should be_ok
47
+ data.delete('3')
48
+ verify_result(@s.docname(:md) => data,@s.docname(:md_size)=>'3')
49
+ end
50
+ end
51
+ end
@@ -18,6 +18,7 @@ describe "RhoconnectApiGetSourceParams" do
18
18
  {"name"=>"callback_url", "value"=>nil, "type"=>"string"},
19
19
  {"name"=>"poll_interval", "value"=>300, "type"=>"integer"},
20
20
  {"name"=>"retry_limit", "type"=>"integer", "value"=>0},
21
+ {"name"=>"simulate_time", "value"=>0, "type"=>"integer"},
21
22
  {"name"=>"partition_type", "value"=>"user", "type"=>"string"},
22
23
  {"name"=>"sync_type", "value"=>"incremental", "type"=>"string"},
23
24
  {"name"=>"belongs_to", "type"=>"string", "value"=>nil},
@@ -0,0 +1,24 @@
1
+ require File.join(File.dirname(__FILE__),'..','api_helper')
2
+
3
+ describe "RhoconnectApiUpdateSourceParams" do
4
+ it_should_behave_like "ApiHelper" do
5
+ it "should set poll_interval to 99 seconds" do
6
+ @s1 = Source.load(@s.id,@s_params)
7
+ before = @s1.poll_interval.to_i
8
+ post "/api/source/update_source_params", :api_token => @api_token,
9
+ :source_name => @s_fields[:name], :user_name => @u_fields[:login], :data => {:poll_interval => 99}
10
+ last_response.should be_ok
11
+ @s2 = Source.load(@s.id,@s_params)
12
+ after = @s2.poll_interval
13
+ before.should == 300
14
+ after.should == 99
15
+ end
16
+
17
+ it "should fail to update the source if param is not found" do
18
+ post "/api/source/update_source_params", :api_token => @api_token,
19
+ :source_name => @s_fields[:name], :user_name => @u_fields[:login], :data => {:invalid_param => "invalid_data"}
20
+ last_response.status.should == 500
21
+ last_response.body.match('undefined method').should_not be_nil
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,19 @@
1
+ require File.join(File.dirname(__FILE__),'api','api_helper')
2
+
3
+ # these specs are executed only with Async support
4
+ if RUBY_VERSION =~ /1.9/
5
+ describe "BasicEventMachineTest with Threads" do
6
+ it_should_behave_like "ApiHelper" do
7
+ it "should run EventMachine gracefully and schedule callback execution in thread" do
8
+ f = Fiber.current
9
+ operation = proc { res = 1 }
10
+ operation_res = 0
11
+ callback = proc { |proc_res| operation_res = proc_res; f.resume }
12
+ EventMachine.defer operation, callback
13
+ Fiber.yield
14
+ # this code should be executed only after the thread's return
15
+ operation_res.should == 1
16
+ end
17
+ end
18
+ end
19
+ end
@@ -38,8 +38,8 @@ describe "ClientSync" do
38
38
  end
39
39
 
40
40
  let(:mock_schema) { {"property" => { "name" => "string", "brand" => "string" }, "version" => "1.0"} }
41
- let(:sha1) { get_sha1(mock_schema.to_json) }
42
-
41
+ let(:sha1) { get_sha1(mock_schema['version']) }
42
+
43
43
  before(:each) do
44
44
  @s = Source.load(@s_fields[:name],@s_params)
45
45
  @cs = ClientSync.new(@s,@c,2)
@@ -699,6 +699,7 @@ describe "ClientSync" do
699
699
  set_state('test_db_storage' => @data)
700
700
  ClientSync.bulk_data(:user,@c)
701
701
  BulkDataJob.perform("data_name" => bulk_data_docname(@a.id,@u.id))
702
+ BulkDataJob.after_perform_x("data_name" => bulk_data_docname(@a.id,@u.id))
702
703
  ClientSync.bulk_data(:user,@c).should == {:result => :url,
703
704
  :url => BulkData.load(bulk_data_docname(@a.id,@u.id)).url}
704
705
  verify_result(
@@ -707,6 +708,18 @@ describe "ClientSync" do
707
708
  "source:#{@a_fields[:name]}:#{@u_fields[:login]}:#{@s_fields[:name]}:md_copy" => @data)
708
709
  end
709
710
 
711
+ it "should return empty bulk data url if there are errors in query" do
712
+ ClientSync.bulk_data(:user,@c)
713
+ BulkDataJob.perform("data_name" => bulk_data_docname(@a.id,@u.id))
714
+ BulkDataJob.after_perform_x("data_name" => bulk_data_docname(@a.id,@u.id))
715
+ errordoc = @s.docname(:errors) # source SampleAdapter
716
+ operation = 'query'
717
+ Store.lock(errordoc) do
718
+ Store.put_data(errordoc,{"#{operation}-error"=>{'message'=>"Some exception message"}}, true)
719
+ end
720
+ ClientSync.bulk_data(:user,@c).should == {:result => :url, :url => ''}
721
+ end
722
+
710
723
  it "should escape bulk data url" do
711
724
  name = 'a b'
712
725
  data = BulkData.create(:name => bulk_data_docname(@a.id,name),
@@ -715,6 +728,7 @@ describe "ClientSync" do
715
728
  :user_id => name,
716
729
  :sources => [@s_fields[:name]])
717
730
  BulkDataJob.perform("data_name" => bulk_data_docname(@a.id,name))
731
+ BulkDataJob.after_perform_x("data_name" => bulk_data_docname(@a.id,name))
718
732
  data = BulkData.load(bulk_data_docname(@a.id,name))
719
733
  data.url.should match /a%20b/
720
734
  data.delete
@@ -725,6 +739,7 @@ describe "ClientSync" do
725
739
  @s.partition = :app
726
740
  ClientSync.bulk_data(:app,@c)
727
741
  BulkDataJob.perform("data_name" => bulk_data_docname(@a.id,"*"))
742
+ BulkDataJob.after_perform_x("data_name" => bulk_data_docname(@a.id,"*"))
728
743
  ClientSync.bulk_data(:app,@c).should == {:result => :url,
729
744
  :url => BulkData.load(bulk_data_docname(@a.id,"*")).url}
730
745
  verify_result(
@@ -738,6 +753,7 @@ describe "ClientSync" do
738
753
  @s.sync_type = :bulk_sync_only
739
754
  ClientSync.bulk_data(:user,@c)
740
755
  BulkDataJob.perform("data_name" => bulk_data_docname(@a.id,@u.id))
756
+ BulkDataJob.after_perform_x("data_name" => bulk_data_docname(@a.id,@u.id))
741
757
  ClientSync.bulk_data(:user,@c).should == {:result => :url,
742
758
  :url => BulkData.load(bulk_data_docname(@a.id,@u.id)).url}
743
759
  verify_result(
@@ -751,6 +767,7 @@ describe "ClientSync" do
751
767
  Rhoconnect.blackberry_bulk_sync = true
752
768
  ClientSync.bulk_data(:user,@c)
753
769
  BulkDataJob.perform("data_name" => bulk_data_docname(@a.id,@u.id))
770
+ BulkDataJob.after_perform_x("data_name" => bulk_data_docname(@a.id,@u.id))
754
771
  data = BulkData.load(bulk_data_docname(@a.id,@u.id))
755
772
  ClientSync.bulk_data(:user,@c).should == {:result => :url, :url => data.url}
756
773
  File.delete(data.dbfile)