rhoconnect 3.0.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.
- data/CHANGELOG +208 -0
- data/CREDITS +38 -0
- data/Gemfile +18 -0
- data/Gemfile.lock +97 -0
- data/LICENSE +75 -0
- data/README.md +10 -0
- data/Rakefile +82 -0
- data/bench/bench +7 -0
- data/bench/bench_runner.rb +112 -0
- data/bench/benchapp/Gemfile +21 -0
- data/bench/benchapp/Gemfile.lock +76 -0
- data/bench/benchapp/Rakefile +22 -0
- data/bench/benchapp/application.rb +39 -0
- data/bench/benchapp/config.ru +36 -0
- data/bench/benchapp/settings/license.key +1 -0
- data/bench/benchapp/settings/settings.yml +20 -0
- data/bench/benchapp/sources/mock_adapter.rb +55 -0
- data/bench/benchapp/sources/queue_mock_adapter.rb +2 -0
- data/bench/benchapp/spec/sources/mock_adapter_spec.rb +25 -0
- data/bench/benchapp/spec/sources/queue_mock_adapter_spec.rb +25 -0
- data/bench/benchapp/spec/spec_helper.rb +42 -0
- data/bench/blobapp/Gemfile +31 -0
- data/bench/blobapp/Gemfile.lock +103 -0
- data/bench/blobapp/Rakefile +25 -0
- data/bench/blobapp/application.rb +44 -0
- data/bench/blobapp/config.ru +36 -0
- data/bench/blobapp/settings/license.key +1 -0
- data/bench/blobapp/settings/settings.yml +16 -0
- data/bench/blobapp/sources/blob_adapter.rb +71 -0
- data/bench/blobapp/spec/sources/blob_adapter_spec.rb +25 -0
- data/bench/blobapp/spec/spec_helper.rb +42 -0
- data/bench/lib/bench/cli.rb +16 -0
- data/bench/lib/bench/logging.rb +13 -0
- data/bench/lib/bench/mock_client.rb +41 -0
- data/bench/lib/bench/result.rb +50 -0
- data/bench/lib/bench/runner.rb +107 -0
- data/bench/lib/bench/session.rb +67 -0
- data/bench/lib/bench/statistics.rb +56 -0
- data/bench/lib/bench/test_data.rb +98 -0
- data/bench/lib/bench/timer.rb +10 -0
- data/bench/lib/bench/utils.rb +49 -0
- data/bench/lib/bench.rb +129 -0
- data/bench/lib/testdata/100-data.txt +148 -0
- data/bench/lib/testdata/5-data.txt +9 -0
- data/bench/lib/testdata/images/icon.ico +0 -0
- data/bench/lib/testdata/images/icon.png +0 -0
- data/bench/lib/testdata/images/loading-Landscape.png +0 -0
- data/bench/lib/testdata/images/loading-LandscapeLeft.png +0 -0
- data/bench/lib/testdata/images/loading-LandscapeRight.png +0 -0
- data/bench/lib/testdata/images/loading-Portrait.png +0 -0
- data/bench/lib/testdata/images/loading-PortraitUpsideDown.png +0 -0
- data/bench/lib/testdata/images/loading.png +0 -0
- data/bench/lib/testdata/images/loading@2x.png +0 -0
- data/bench/run_bench.sh +42 -0
- data/bench/run_blob_script.sh +3 -0
- data/bench/run_cud_script.sh +3 -0
- data/bench/run_query_md_script.sh +3 -0
- data/bench/run_query_only_script.sh +3 -0
- data/bench/run_query_script.sh +3 -0
- data/bench/scripts/blob_cud_script.rb +98 -0
- data/bench/scripts/cud_script.rb +92 -0
- data/bench/scripts/helpers.rb +101 -0
- data/bench/scripts/query_md_script.rb +45 -0
- data/bench/scripts/query_only_script.rb +51 -0
- data/bench/scripts/query_script.rb +45 -0
- data/bench/spec/bench_spec_helper.rb +33 -0
- data/bench/spec/logging_spec.rb +15 -0
- data/bench/spec/mock_adapter_spec.rb +61 -0
- data/bench/spec/mock_client_spec.rb +65 -0
- data/bench/spec/result_spec.rb +61 -0
- data/bench/spec/utils_spec.rb +36 -0
- data/bin/rhoconnect +34 -0
- data/bin/rhoconnect-setup +84 -0
- data/doc/async-jobs.txt +69 -0
- data/doc/authentication.txt +76 -0
- data/doc/benchmarks.txt +168 -0
- data/doc/blob-sync.txt +130 -0
- data/doc/bulk-sync.txt +102 -0
- data/doc/client.txt +432 -0
- data/doc/command-line.txt +210 -0
- data/doc/contributing.txt +60 -0
- data/doc/deploying.txt +82 -0
- data/doc/install.txt +28 -0
- data/doc/introduction.txt +20 -0
- data/doc/licensing.txt +18 -0
- data/doc/metadata.txt +458 -0
- data/doc/migration.txt +182 -0
- data/doc/public/css/print.css +29 -0
- data/doc/public/css/screen.css +257 -0
- data/doc/public/css/style.css +20 -0
- data/doc/push.txt +135 -0
- data/doc/release.txt +41 -0
- data/doc/rest-api.txt +367 -0
- data/doc/source-adapters.txt +325 -0
- data/doc/stats-middleware.txt +69 -0
- data/doc/testing.txt +222 -0
- data/doc/tutorial.txt +315 -0
- data/doc/web-console.txt +35 -0
- data/examples/simple/Rakefile +14 -0
- data/examples/simple/application.rb +27 -0
- data/examples/simple/config.ru +49 -0
- data/examples/simple/settings/license.key +1 -0
- data/examples/simple/settings/settings.yml +23 -0
- data/examples/simple/sources/sample_adapter.rb +5 -0
- data/examples/simple/sources/simple_adapter.rb +5 -0
- data/generators/rhoconnect.rb +119 -0
- data/generators/templates/application/Gemfile +21 -0
- data/generators/templates/application/Rakefile +22 -0
- data/generators/templates/application/application.rb +39 -0
- data/generators/templates/application/config.ru +36 -0
- data/generators/templates/application/settings/license.key +1 -0
- data/generators/templates/application/settings/settings.yml +14 -0
- data/generators/templates/application/spec/spec_helper.rb +42 -0
- data/generators/templates/source/source_adapter.rb +47 -0
- data/generators/templates/source/source_spec.rb +25 -0
- data/install.sh +408 -0
- data/installer/unix-like/rho_connect_install_checkers.rb +140 -0
- data/installer/unix-like/rho_connect_install_constants.rb +51 -0
- data/installer/unix-like/rho_connect_install_debian.rb +63 -0
- data/installer/unix-like/rho_connect_install_dnd.rb +58 -0
- data/installer/unix-like/rho_connect_install_get_params.rb +30 -0
- data/installer/unix-like/rho_connect_install_installers.rb +142 -0
- data/installer/unix-like/rho_connect_install_utilities.rb +85 -0
- data/installer/unix-like/rho_connect_install_yum.rb +63 -0
- data/installer/unix-like/rhoinstaller.rb +89 -0
- data/installer/utils/create_texts.rb +366 -0
- data/installer/utils/install_test.rb +140 -0
- data/installer/windows/EnvVarUpdate.nsh +328 -0
- data/installer/windows/ServiceLib.nsh +369 -0
- data/installer/windows/configUi.ini +44 -0
- data/installer/windows/icon.ico +0 -0
- data/installer/windows/rhosync.nsi +418 -0
- data/installer/windows/uninstall.bat +7 -0
- data/lib/rhoconnect/api/admin/get_api_token.rb +14 -0
- data/lib/rhoconnect/api/admin/get_license_info.rb +8 -0
- data/lib/rhoconnect/api/admin/login.rb +6 -0
- data/lib/rhoconnect/api/admin/reset.rb +10 -0
- data/lib/rhoconnect/api/admin/stats.rb +21 -0
- data/lib/rhoconnect/api/application/bulk_data.rb +7 -0
- data/lib/rhoconnect/api/application/clientcreate.rb +8 -0
- data/lib/rhoconnect/api/application/clientlogin.rb +6 -0
- data/lib/rhoconnect/api/application/clientregister.rb +6 -0
- data/lib/rhoconnect/api/application/clientreset.rb +6 -0
- data/lib/rhoconnect/api/application/query.rb +7 -0
- data/lib/rhoconnect/api/application/queue_updates.rb +6 -0
- data/lib/rhoconnect/api/application/search.rb +6 -0
- data/lib/rhoconnect/api/client/create_client.rb +3 -0
- data/lib/rhoconnect/api/client/delete_client.rb +5 -0
- data/lib/rhoconnect/api/client/get_client_params.rb +3 -0
- data/lib/rhoconnect/api/client/list_client_docs.rb +12 -0
- data/lib/rhoconnect/api/client/list_clients.rb +3 -0
- data/lib/rhoconnect/api/client/ping.rb +7 -0
- data/lib/rhoconnect/api/source/get_adapter.rb +3 -0
- data/lib/rhoconnect/api/source/get_db_doc.rb +7 -0
- data/lib/rhoconnect/api/source/get_source_params.rb +3 -0
- data/lib/rhoconnect/api/source/list_source_docs.rb +10 -0
- data/lib/rhoconnect/api/source/list_sources.rb +15 -0
- data/lib/rhoconnect/api/source/push_deletes.rb +8 -0
- data/lib/rhoconnect/api/source/push_objects.rb +8 -0
- data/lib/rhoconnect/api/source/save_adapter.rb +3 -0
- data/lib/rhoconnect/api/source/set_db_doc.rb +8 -0
- data/lib/rhoconnect/api/source/set_refresh_time.rb +8 -0
- data/lib/rhoconnect/api/source/upload_file.rb +4 -0
- data/lib/rhoconnect/api/user/create_user.rb +7 -0
- data/lib/rhoconnect/api/user/delete_user.rb +9 -0
- data/lib/rhoconnect/api/user/list_users.rb +3 -0
- data/lib/rhoconnect/api/user/update_user.rb +4 -0
- data/lib/rhoconnect/api_token.rb +19 -0
- data/lib/rhoconnect/app.rb +76 -0
- data/lib/rhoconnect/bulk_data/bulk_data.rb +88 -0
- data/lib/rhoconnect/bulk_data/syncdb.index.schema +4 -0
- data/lib/rhoconnect/bulk_data/syncdb.schema +41 -0
- data/lib/rhoconnect/bulk_data.rb +2 -0
- data/lib/rhoconnect/client.rb +96 -0
- data/lib/rhoconnect/client_sync.rb +412 -0
- data/lib/rhoconnect/console/app/helpers/auth_helper.rb +22 -0
- data/lib/rhoconnect/console/app/helpers/extensions.rb +19 -0
- data/lib/rhoconnect/console/app/helpers/helpers.rb +57 -0
- data/lib/rhoconnect/console/app/public/ThickBox.css +649 -0
- data/lib/rhoconnect/console/app/public/home.css +438 -0
- data/lib/rhoconnect/console/app/public/images/foot_logo_rhoconnect.png +0 -0
- data/lib/rhoconnect/console/app/public/images/header_halo.jpg +0 -0
- data/lib/rhoconnect/console/app/public/images/land_separator.gif +0 -0
- data/lib/rhoconnect/console/app/public/images/landing_header.jpg +0 -0
- data/lib/rhoconnect/console/app/public/images/logo_rhoconnect.png +0 -0
- data/lib/rhoconnect/console/app/public/images/rhomobile_rhohub_logo.png +0 -0
- data/lib/rhoconnect/console/app/public/images/tabs_separator.png +0 -0
- data/lib/rhoconnect/console/app/public/jqplot/excanvas.min.js +35 -0
- data/lib/rhoconnect/console/app/public/jqplot/jqplot.barRenderer.min.js +34 -0
- data/lib/rhoconnect/console/app/public/jqplot/jqplot.canvasAxisLabelRenderer.js +187 -0
- data/lib/rhoconnect/console/app/public/jqplot/jqplot.canvasAxisTickRenderer.js +226 -0
- data/lib/rhoconnect/console/app/public/jqplot/jqplot.canvasTextRenderer.js +408 -0
- data/lib/rhoconnect/console/app/public/jqplot/jqplot.categoryAxisRenderer.min.js +34 -0
- data/lib/rhoconnect/console/app/public/jqplot/jqplot.cursor.js +952 -0
- data/lib/rhoconnect/console/app/public/jqplot/jqplot.dateAxisRenderer.js +313 -0
- data/lib/rhoconnect/console/app/public/jqplot/jqplot.dateAxisRenderer.min.js +34 -0
- data/lib/rhoconnect/console/app/public/jqplot/jqplot.pointLabels.min.js +34 -0
- data/lib/rhoconnect/console/app/public/jqplot/jquery-1.4.2.min.js +154 -0
- data/lib/rhoconnect/console/app/public/jqplot/jquery.jqplot.min.css +1 -0
- data/lib/rhoconnect/console/app/public/jqplot/jquery.jqplot.min.js +34 -0
- data/lib/rhoconnect/console/app/public/main.css +7 -0
- data/lib/rhoconnect/console/app/public/reset.css +76 -0
- data/lib/rhoconnect/console/app/public/style.css +2201 -0
- data/lib/rhoconnect/console/app/public/text.txt +0 -0
- data/lib/rhoconnect/console/app/routes/adapter.rb +28 -0
- data/lib/rhoconnect/console/app/routes/auth.rb +29 -0
- data/lib/rhoconnect/console/app/routes/client.rb +31 -0
- data/lib/rhoconnect/console/app/routes/docs.rb +145 -0
- data/lib/rhoconnect/console/app/routes/heroku.rb +19 -0
- data/lib/rhoconnect/console/app/routes/home.rb +63 -0
- data/lib/rhoconnect/console/app/routes/timing.rb +242 -0
- data/lib/rhoconnect/console/app/routes/user.rb +117 -0
- data/lib/rhoconnect/console/app/views/adapter.erb +16 -0
- data/lib/rhoconnect/console/app/views/client.erb +30 -0
- data/lib/rhoconnect/console/app/views/content.erb +14 -0
- data/lib/rhoconnect/console/app/views/doc.erb +8 -0
- data/lib/rhoconnect/console/app/views/docdata.erb +28 -0
- data/lib/rhoconnect/console/app/views/docs.erb +30 -0
- data/lib/rhoconnect/console/app/views/edituser.erb +13 -0
- data/lib/rhoconnect/console/app/views/headermenu.erb +40 -0
- data/lib/rhoconnect/console/app/views/home.erb +24 -0
- data/lib/rhoconnect/console/app/views/index.erb +58 -0
- data/lib/rhoconnect/console/app/views/jqplot.erb +52 -0
- data/lib/rhoconnect/console/app/views/layout.erb +165 -0
- data/lib/rhoconnect/console/app/views/login.erb +26 -0
- data/lib/rhoconnect/console/app/views/newuser.erb +17 -0
- data/lib/rhoconnect/console/app/views/ping.erb +28 -0
- data/lib/rhoconnect/console/app/views/result.erb +11 -0
- data/lib/rhoconnect/console/app/views/rightboxlinks.erb +15 -0
- data/lib/rhoconnect/console/app/views/select_doc.erb +17 -0
- data/lib/rhoconnect/console/app/views/upload_doc.erb +23 -0
- data/lib/rhoconnect/console/app/views/user.erb +29 -0
- data/lib/rhoconnect/console/app/views/users.erb +12 -0
- data/lib/rhoconnect/console/rhoconnect_api.rb +245 -0
- data/lib/rhoconnect/console/server.rb +32 -0
- data/lib/rhoconnect/console.rb +3 -0
- data/lib/rhoconnect/cors.rb +229 -0
- data/lib/rhoconnect/credential.rb +9 -0
- data/lib/rhoconnect/db_adapter.rb +46 -0
- data/lib/rhoconnect/document.rb +49 -0
- data/lib/rhoconnect/dynamic_adapter.rb +91 -0
- data/lib/rhoconnect/generator.rb +1 -0
- data/lib/rhoconnect/jobs/bulk_data_job.rb +203 -0
- data/lib/rhoconnect/jobs/ping_job.rb +46 -0
- data/lib/rhoconnect/jobs/source_job.rb +16 -0
- data/lib/rhoconnect/license.rb +86 -0
- data/lib/rhoconnect/lock_ops.rb +11 -0
- data/lib/rhoconnect/model.rb +414 -0
- data/lib/rhoconnect/ping/android.rb +56 -0
- data/lib/rhoconnect/ping/apple.rb +52 -0
- data/lib/rhoconnect/ping/blackberry.rb +56 -0
- data/lib/rhoconnect/ping.rb +3 -0
- data/lib/rhoconnect/read_state.rb +31 -0
- data/lib/rhoconnect/rho_indifferent_access.rb +88 -0
- data/lib/rhoconnect/server/views/index.erb +13 -0
- data/lib/rhoconnect/server.rb +286 -0
- data/lib/rhoconnect/source.rb +289 -0
- data/lib/rhoconnect/source_adapter.rb +123 -0
- data/lib/rhoconnect/source_sync.rb +302 -0
- data/lib/rhoconnect/stats/middleware.rb +20 -0
- data/lib/rhoconnect/stats/record.rb +108 -0
- data/lib/rhoconnect/store.rb +232 -0
- data/lib/rhoconnect/tasks.rb +350 -0
- data/lib/rhoconnect/test_methods.rb +220 -0
- data/lib/rhoconnect/user.rb +95 -0
- data/lib/rhoconnect/version.rb +3 -0
- data/lib/rhoconnect/x_domain_session_wrapper.rb +53 -0
- data/lib/rhoconnect.rb +285 -0
- data/rhoconnect.gemspec +67 -0
- data/spec/api/admin/api_token_spec.rb +14 -0
- data/spec/api/admin/get_api_token_spec.rb +36 -0
- data/spec/api/admin/get_license_info_spec.rb +38 -0
- data/spec/api/admin/reset_spec.rb +22 -0
- data/spec/api/admin/stats_spec.rb +66 -0
- data/spec/api/api_helper.rb +21 -0
- data/spec/api/application/rhoconnect_api_spec.rb +548 -0
- data/spec/api/client/create_client_spec.rb +13 -0
- data/spec/api/client/delete_client_spec.rb +13 -0
- data/spec/api/client/get_client_params_spec.rb +18 -0
- data/spec/api/client/list_client_docs_spec.rb +32 -0
- data/spec/api/client/list_clients_spec.rb +22 -0
- data/spec/api/client/ping_spec.rb +23 -0
- data/spec/api/rhosync_api_spec.rb.orig +606 -0
- data/spec/api/source/adapter_spec.rb +29 -0
- data/spec/api/source/get_db_doc_spec.rb +21 -0
- data/spec/api/source/get_source_params_spec.rb +32 -0
- data/spec/api/source/list_source_docs_spec.rb +25 -0
- data/spec/api/source/list_sources_spec.rb +26 -0
- data/spec/api/source/push_deletes_spec.rb +18 -0
- data/spec/api/source/push_objects_spec.rb +27 -0
- data/spec/api/source/set_db_doc_spec.rb +19 -0
- data/spec/api/source/set_refresh_time_spec.rb +43 -0
- data/spec/api/source/upload_file_spec.rb +26 -0
- data/spec/api/user/create_user_spec.rb +16 -0
- data/spec/api/user/delete_user_spec.rb +36 -0
- data/spec/api/user/list_users_spec.rb +30 -0
- data/spec/api/user/update_user_spec.rb +31 -0
- data/spec/api_token_spec.rb +14 -0
- data/spec/app_spec.rb +18 -0
- data/spec/apps/emptyapp/application.rb +27 -0
- data/spec/apps/emptyapp/settings/license.key +1 -0
- data/spec/apps/emptyapp/settings/settings.yml +14 -0
- data/spec/apps/rhotestapp/Rakefile +1 -0
- data/spec/apps/rhotestapp/application.rb +19 -0
- data/spec/apps/rhotestapp/config.ru +1 -0
- data/spec/apps/rhotestapp/settings/apple_fake_cert.pem +1 -0
- data/spec/apps/rhotestapp/settings/license.key +1 -0
- data/spec/apps/rhotestapp/settings/settings.yml +36 -0
- data/spec/apps/rhotestapp/sources/base_adapter.rb +9 -0
- data/spec/apps/rhotestapp/sources/fixed_schema_adapter.rb +28 -0
- data/spec/apps/rhotestapp/sources/sample_adapter.rb +71 -0
- data/spec/apps/rhotestapp/sources/simple_adapter.rb +41 -0
- data/spec/apps/rhotestapp/sources/sub_adapter.rb +7 -0
- data/spec/apps/rhotestapp/vendor/mygem-0.1.0/lib/mygem/mygem.rb +8 -0
- data/spec/apps/rhotestapp/vendor/mygem-0.1.0/lib/mygem.rb +1 -0
- data/spec/bulk_data/bulk_data_spec.rb +97 -0
- data/spec/client_spec.rb +124 -0
- data/spec/client_sync_spec.rb +774 -0
- data/spec/doc/base.html +72 -0
- data/spec/doc/doc_spec.rb +376 -0
- data/spec/doc/footer.html +4 -0
- data/spec/doc/header.html +30 -0
- data/spec/document_spec.rb +31 -0
- data/spec/dynamic_adapter_spec.rb +43 -0
- data/spec/factories/factories.rb +17 -0
- data/spec/generator/generator_spec.rb +58 -0
- data/spec/generator/generator_spec_helper.rb +9 -0
- data/spec/jobs/bulk_data_job_spec.rb +125 -0
- data/spec/jobs/ping_job_spec.rb +102 -0
- data/spec/jobs/source_job_spec.rb +29 -0
- data/spec/license_spec.rb +66 -0
- data/spec/model_spec.rb +273 -0
- data/spec/perf/bulk_data_perf_spec.rb +32 -0
- data/spec/perf/perf_spec_helper.rb +50 -0
- data/spec/perf/store_perf_spec.rb +27 -0
- data/spec/ping/android_spec.rb +91 -0
- data/spec/ping/apple_spec.rb +70 -0
- data/spec/ping/blackberry_spec.rb +62 -0
- data/spec/read_state_spec.rb +35 -0
- data/spec/rhosync_spec.rb +75 -0
- data/spec/server/cors_spec.rb +287 -0
- data/spec/server/server_spec.rb +470 -0
- data/spec/server/x_domain_session_wrapper_spec.rb +150 -0
- data/spec/source_adapter_spec.rb +125 -0
- data/spec/source_spec.rb +114 -0
- data/spec/source_sync_spec.rb +328 -0
- data/spec/spec.opts +4 -0
- data/spec/spec_helper.rb +231 -0
- data/spec/stats/middleware_spec.rb +53 -0
- data/spec/stats/record_spec.rb +92 -0
- data/spec/store_spec.rb +251 -0
- data/spec/support/shared_examples.rb +168 -0
- data/spec/sync_states_spec.rb +72 -0
- data/spec/test_methods_spec.rb +134 -0
- data/spec/testdata/1000-data.txt +1414 -0
- data/spec/testdata/compressed/compress-data.txt +1 -0
- data/spec/testdata/upload1.txt +1 -0
- data/spec/testdata/upload2.txt +1 -0
- data/spec/user_spec.rb +139 -0
- data/tasks/redis.rake +206 -0
- metadata +706 -0
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
module Rhoconnect
|
|
2
|
+
class SourceSync
|
|
3
|
+
attr_reader :adapter
|
|
4
|
+
|
|
5
|
+
def initialize(source)
|
|
6
|
+
@source = source
|
|
7
|
+
raise InvalidArgumentError.new('Invalid source') if @source.nil?
|
|
8
|
+
raise InvalidArgumentError.new('Invalid app for source') unless @source.app
|
|
9
|
+
@adapter = SourceAdapter.create(@source)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# CUD Operations
|
|
13
|
+
def create(client_id)
|
|
14
|
+
_measure_and_process_cud('create',client_id)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def update(client_id)
|
|
18
|
+
_measure_and_process_cud('update',client_id)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def delete(client_id)
|
|
22
|
+
_measure_and_process_cud('delete',client_id)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Pass through CUD to adapter, no data stored
|
|
26
|
+
def pass_through_cud(cud_params,query_params)
|
|
27
|
+
return if _auth_op('login') == false
|
|
28
|
+
res,processed_objects = {},[]
|
|
29
|
+
begin
|
|
30
|
+
['create','update','delete'].each do |op|
|
|
31
|
+
key,objects = op,cud_params[op]
|
|
32
|
+
objects.each do |key,value|
|
|
33
|
+
case op
|
|
34
|
+
when 'create'
|
|
35
|
+
@adapter.send(op.to_sym,value)
|
|
36
|
+
when 'update'
|
|
37
|
+
value['id'] = key
|
|
38
|
+
@adapter.send(op.to_sym,value)
|
|
39
|
+
when 'delete'
|
|
40
|
+
value['id'] = key
|
|
41
|
+
@adapter.send(op.to_sym,value)
|
|
42
|
+
end
|
|
43
|
+
processed_objects << key
|
|
44
|
+
end if objects
|
|
45
|
+
end
|
|
46
|
+
rescue Exception => e
|
|
47
|
+
log "Error in pass through method: #{e.message}"
|
|
48
|
+
res['error'] = {'message' => e.message }
|
|
49
|
+
end
|
|
50
|
+
_auth_op('logoff')
|
|
51
|
+
res['processed'] = processed_objects
|
|
52
|
+
res.to_json
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Read Operation; params are query arguments
|
|
56
|
+
def read(client_id=nil,params=nil)
|
|
57
|
+
_read('query',client_id,params)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def search(client_id=nil,params=nil)
|
|
61
|
+
return if _auth_op('login',client_id) == false
|
|
62
|
+
res = _read('search',client_id,params)
|
|
63
|
+
_auth_op('logoff',client_id)
|
|
64
|
+
res
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def process_cud(client_id)
|
|
68
|
+
if @source.cud_queue or @source.queue
|
|
69
|
+
async(:cud,@source.cud_queue || @source.queue,client_id)
|
|
70
|
+
else
|
|
71
|
+
do_cud(client_id)
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def do_cud(client_id)
|
|
76
|
+
return if _auth_op('login') == false
|
|
77
|
+
self.create(client_id)
|
|
78
|
+
self.update(client_id)
|
|
79
|
+
self.delete(client_id)
|
|
80
|
+
_auth_op('logoff')
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def process_query(params=nil)
|
|
84
|
+
if @source.query_queue or @source.queue
|
|
85
|
+
async(:query,@source.query_queue || @source.queue,nil,params)
|
|
86
|
+
else
|
|
87
|
+
do_query(params)
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def do_query(params=nil)
|
|
92
|
+
result = nil
|
|
93
|
+
@source.if_need_refresh do
|
|
94
|
+
Stats::Record.update("source:query:#{@source.name}") do
|
|
95
|
+
return if _auth_op('login') == false
|
|
96
|
+
result = self.read(nil,params)
|
|
97
|
+
_auth_op('logoff')
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
result
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# Enqueue a job for the source based on job type
|
|
104
|
+
def async(job_type,queue_name,client_id=nil,params=nil)
|
|
105
|
+
SourceJob.queue = queue_name
|
|
106
|
+
Resque.enqueue(SourceJob,job_type,@source.id,
|
|
107
|
+
@source.app_id,@source.user_id,client_id,params)
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def push_objects(objects,timeout=10,raise_on_expire=false)
|
|
111
|
+
@source.lock(:md,timeout,raise_on_expire) do |s|
|
|
112
|
+
doc = @source.get_data(:md)
|
|
113
|
+
orig_doc_size = doc.size
|
|
114
|
+
objects.each do |id,obj|
|
|
115
|
+
doc[id] ||= {}
|
|
116
|
+
doc[id].merge!(obj)
|
|
117
|
+
end
|
|
118
|
+
diff_count = doc.size - orig_doc_size
|
|
119
|
+
@source.put_data(:md,doc)
|
|
120
|
+
@source.update_count(:md_size,diff_count)
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def push_deletes(objects,timeout=10,raise_on_expire=false)
|
|
125
|
+
@source.lock(:md,timeout,raise_on_expire) do |s|
|
|
126
|
+
doc = @source.get_data(:md)
|
|
127
|
+
orig_doc_size = doc.size
|
|
128
|
+
objects.each do |id|
|
|
129
|
+
doc.delete(id)
|
|
130
|
+
end
|
|
131
|
+
diff_count = doc.size - orig_doc_size
|
|
132
|
+
@source.put_data(:md,doc)
|
|
133
|
+
@source.update_count(:md_size,diff_count)
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
private
|
|
138
|
+
def _auth_op(operation,client_id=-1)
|
|
139
|
+
edockey = client_id == -1 ? @source.docname(:errors) :
|
|
140
|
+
Client.load(client_id,{:source_name => @source.name}).docname(:search_errors)
|
|
141
|
+
begin
|
|
142
|
+
Store.flash_data(edockey) if operation == 'login'
|
|
143
|
+
@adapter.send operation
|
|
144
|
+
rescue Exception => e
|
|
145
|
+
log "SourceAdapter raised #{operation} exception: #{e}"
|
|
146
|
+
log e.backtrace.join("\n")
|
|
147
|
+
Store.put_data(edockey,{"#{operation}-error"=>{'message'=>e.message}},true)
|
|
148
|
+
return false
|
|
149
|
+
end
|
|
150
|
+
true
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def _process_create(client,key,value,links,creates,deletes)
|
|
154
|
+
# Perform operation
|
|
155
|
+
link = @adapter.create value
|
|
156
|
+
# Store object-id link for the client
|
|
157
|
+
# If we have a link, store object in client document
|
|
158
|
+
# Otherwise, store object for delete on client
|
|
159
|
+
if link
|
|
160
|
+
links ||= {}
|
|
161
|
+
links[key] = { 'l' => link.to_s }
|
|
162
|
+
creates ||= {}
|
|
163
|
+
creates[link.to_s] = value
|
|
164
|
+
else
|
|
165
|
+
deletes ||= {}
|
|
166
|
+
deletes[key] = value
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
def _process_update(client,key,value)
|
|
171
|
+
begin
|
|
172
|
+
# Add id to object hash to forward to backend call
|
|
173
|
+
value['id'] = key
|
|
174
|
+
# Perform operation
|
|
175
|
+
@adapter.update value
|
|
176
|
+
rescue Exception => e
|
|
177
|
+
# TODO: This will be slow!
|
|
178
|
+
cd = client.get_data(:cd)
|
|
179
|
+
client.put_data(:update_rollback,{key => cd[key]},true) if cd[key]
|
|
180
|
+
raise e
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
def _process_delete(client,key,value,dels)
|
|
185
|
+
value['id'] = key
|
|
186
|
+
# Perform operation
|
|
187
|
+
@adapter.delete value
|
|
188
|
+
dels ||= {}
|
|
189
|
+
dels[key] = value
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
def _measure_and_process_cud(operation,client_id)
|
|
193
|
+
Stats::Record.update("source:#{operation}:#{@source.name}") do
|
|
194
|
+
_process_cud(operation,client_id)
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
def _process_cud(operation,client_id)
|
|
199
|
+
errors,links,deletes,creates,dels = {},{},{},{},{}
|
|
200
|
+
client = Client.load(client_id,{:source_name => @source.name})
|
|
201
|
+
modified = client.get_data(operation)
|
|
202
|
+
# Process operation queue, one object at a time
|
|
203
|
+
modified.each do |key,value|
|
|
204
|
+
begin
|
|
205
|
+
# Remove object from queue
|
|
206
|
+
modified.delete(key)
|
|
207
|
+
# Call on source adapter to process individual object
|
|
208
|
+
case operation
|
|
209
|
+
when 'create'
|
|
210
|
+
_process_create(client,key,value,links,creates,deletes)
|
|
211
|
+
when 'update'
|
|
212
|
+
_process_update(client,key,value)
|
|
213
|
+
when 'delete'
|
|
214
|
+
_process_delete(client,key,value,dels)
|
|
215
|
+
end
|
|
216
|
+
rescue Exception => e
|
|
217
|
+
log "SourceAdapter raised #{operation} exception: #{e}"
|
|
218
|
+
log e.backtrace.join("\n")
|
|
219
|
+
errors ||= {}
|
|
220
|
+
errors[key] = value
|
|
221
|
+
errors["#{key}-error"] = {'message'=>e.message}
|
|
222
|
+
break
|
|
223
|
+
end
|
|
224
|
+
end
|
|
225
|
+
# Record operation results
|
|
226
|
+
{ "delete_page" => deletes,
|
|
227
|
+
"#{operation}_links" => links,
|
|
228
|
+
"#{operation}_errors" => errors }.each do |doctype,value|
|
|
229
|
+
client.put_data(doctype,value,true) unless value.empty?
|
|
230
|
+
end
|
|
231
|
+
unless operation != 'create' and creates.empty?
|
|
232
|
+
client.put_data(:cd,creates,true)
|
|
233
|
+
client.update_count(:cd_size,creates.size)
|
|
234
|
+
@source.lock(:md) do |s|
|
|
235
|
+
s.put_data(:md,creates,true)
|
|
236
|
+
s.update_count(:md_size,creates.size)
|
|
237
|
+
end
|
|
238
|
+
end
|
|
239
|
+
if operation == 'delete'
|
|
240
|
+
# Clean up deleted objects from master document and corresponding client document
|
|
241
|
+
client.delete_data(:cd,dels)
|
|
242
|
+
client.update_count(:cd_size,-dels.size)
|
|
243
|
+
@source.lock(:md) do |s|
|
|
244
|
+
s.delete_data(:md,dels)
|
|
245
|
+
s.update_count(:md_size,-dels.size)
|
|
246
|
+
end
|
|
247
|
+
end
|
|
248
|
+
# Record rest of queue (if something in the middle failed)
|
|
249
|
+
if modified.empty?
|
|
250
|
+
client.flash_data(operation)
|
|
251
|
+
else
|
|
252
|
+
client.put_data(operation,modified)
|
|
253
|
+
end
|
|
254
|
+
modified.size
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
# Metadata Operation; source adapter returns json
|
|
258
|
+
def _get_data(method)
|
|
259
|
+
if @adapter.respond_to?(method)
|
|
260
|
+
data = @adapter.send(method)
|
|
261
|
+
if data
|
|
262
|
+
@source.put_value(method,data)
|
|
263
|
+
@source.put_value("#{method}_sha1",Digest::SHA1.hexdigest(data))
|
|
264
|
+
end
|
|
265
|
+
end
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
# Read Operation; params are query arguments
|
|
269
|
+
def _read(operation,client_id,params=nil)
|
|
270
|
+
errordoc = nil
|
|
271
|
+
result = nil
|
|
272
|
+
begin
|
|
273
|
+
if operation == 'search'
|
|
274
|
+
client = Client.load(client_id,{:source_name => @source.name})
|
|
275
|
+
errordoc = client.docname(:search_errors)
|
|
276
|
+
compute_token(client.docname(:search_token))
|
|
277
|
+
result = @adapter.search(params)
|
|
278
|
+
@adapter.save(client.docname(:search)) unless @source.is_pass_through?
|
|
279
|
+
else
|
|
280
|
+
errordoc = @source.docname(:errors)
|
|
281
|
+
[:metadata,:schema].each do |method|
|
|
282
|
+
_get_data(method)
|
|
283
|
+
end
|
|
284
|
+
result = @adapter.do_query(params)
|
|
285
|
+
end
|
|
286
|
+
# operation,sync succeeded, remove errors
|
|
287
|
+
Store.lock(errordoc) do
|
|
288
|
+
Store.flash_data(errordoc)
|
|
289
|
+
end
|
|
290
|
+
rescue Exception => e
|
|
291
|
+
# store sync,operation exceptions to be sent to all clients for this source/user
|
|
292
|
+
log "SourceAdapter raised #{operation} exception: #{e}"
|
|
293
|
+
log e.backtrace.join("\n")
|
|
294
|
+
Store.lock(errordoc) do
|
|
295
|
+
Store.put_data(errordoc,{"#{operation}-error"=>{'message'=>e.message}},true)
|
|
296
|
+
end
|
|
297
|
+
end
|
|
298
|
+
# pass through expects result hash
|
|
299
|
+
@source.is_pass_through? ? result : true
|
|
300
|
+
end
|
|
301
|
+
end
|
|
302
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
module Rhoconnect
|
|
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['PATH_INFO']}"
|
|
13
|
+
source_name = env['rack.request.query_hash']["source_name"] if env['rack.request.query_hash']
|
|
14
|
+
metric << ":#{source_name}" if source_name
|
|
15
|
+
Record.save_average(metric,finish - start)
|
|
16
|
+
[status, headers, body]
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
module Rhoconnect
|
|
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 set(metric, value = 0)
|
|
10
|
+
start = (Time.now.to_i / resolution(metric)) * resolution(metric)
|
|
11
|
+
current, current_score = 0, start
|
|
12
|
+
Store.lock(key(metric)) do
|
|
13
|
+
range = Store.db.zrevrange(key(metric), 0, 0)
|
|
14
|
+
if !range.empty?
|
|
15
|
+
member = range[0]
|
|
16
|
+
m_current = member.split(':')[0]
|
|
17
|
+
m_current_score = Store.db.zscore(key(metric), member).to_i
|
|
18
|
+
if m_current_score > (start - resolution(metric))
|
|
19
|
+
Store.db.zrem(key(metric), member)
|
|
20
|
+
current, current_score = m_current, m_current_score
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
value = block_given? ? yield(current, value) : value
|
|
24
|
+
Store.db.zadd(key(metric), current_score, "#{value}:#{start}")
|
|
25
|
+
Store.db.zremrangebyscore(key(metric), 0, start - record_size(metric))
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def add(metric, value = 1)
|
|
30
|
+
set(metric,value) { |current,value| current.to_i + value }
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Saves the accumulated average for a resolution in a metric
|
|
34
|
+
def save_average(metric, value)
|
|
35
|
+
set(metric,value) do |current,value|
|
|
36
|
+
sum = value
|
|
37
|
+
if current.is_a?(String)
|
|
38
|
+
current,sum = current.split(',')
|
|
39
|
+
current = current.to_f
|
|
40
|
+
sum = sum.to_f+value
|
|
41
|
+
end
|
|
42
|
+
"#{current + 1},#{sum}"
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def update(metric)
|
|
47
|
+
if Rhoconnect.stats
|
|
48
|
+
start = Time.now.to_f
|
|
49
|
+
# perform the operations
|
|
50
|
+
yield
|
|
51
|
+
finish = Time.now.to_f
|
|
52
|
+
save_average(metric, finish - start)
|
|
53
|
+
else
|
|
54
|
+
yield
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def keys(glob='*')
|
|
59
|
+
Store.db.keys(key(glob)).collect {|c| c[5..-1]}
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def reset(metric)
|
|
63
|
+
Store.db.del(key(metric))
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def reset_all
|
|
67
|
+
Store.flash_data('stat:*')
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Returns simple string metric
|
|
71
|
+
def get_value(metric)
|
|
72
|
+
Store.get_value(key(metric))
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# Sets a string metric
|
|
76
|
+
def set_value(metric, value)
|
|
77
|
+
Store.set_value(key(metric), value)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# Returns the metric data, uses array indexing
|
|
81
|
+
def range(metric, start, finish = -1)
|
|
82
|
+
Store.db.zrange(key(metric), start, finish)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Returns the resolution for a given metric, default 60 seconds
|
|
86
|
+
def resolution(metric)
|
|
87
|
+
resolution = STATS_RECORD_RESOLUTION rescue nil
|
|
88
|
+
resolution || 60 #=> 1 minute aggregate
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# Returns the # of records to save for a given metric
|
|
92
|
+
def record_size(metric)
|
|
93
|
+
size = STATS_RECORD_SIZE rescue nil
|
|
94
|
+
size || 60 * 24 * 31 #=> 44640 minutes
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# Returns redis object type for a record
|
|
98
|
+
def rtype(metric)
|
|
99
|
+
Store.db.type(key(metric))
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def key(metric)
|
|
103
|
+
"stat:#{metric}"
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
module Rhoconnect
|
|
2
|
+
|
|
3
|
+
class StoreLockException < RuntimeError; end
|
|
4
|
+
|
|
5
|
+
class Store
|
|
6
|
+
RESERVED_ATTRIB_NAMES = ["attrib_type", "id"] unless defined? RESERVED_ATTRIB_NAMES
|
|
7
|
+
@@db = nil
|
|
8
|
+
|
|
9
|
+
class << self
|
|
10
|
+
def db; @@db || @@db = _get_redis end
|
|
11
|
+
|
|
12
|
+
def db=(server=nil)
|
|
13
|
+
@@db = _get_redis(server)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def create(server=nil)
|
|
17
|
+
@@db ||= _get_redis(server)
|
|
18
|
+
raise "Error connecting to Redis store." unless @@db and
|
|
19
|
+
(@@db.is_a?(Redis) or @@db.is_a?(Redis::Client))
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Adds set with given data, replaces existing set
|
|
23
|
+
# if it exists or appends data to the existing set
|
|
24
|
+
# if append flag set to true
|
|
25
|
+
def put_data(dockey,data={},append=false)
|
|
26
|
+
if dockey and data
|
|
27
|
+
flash_data(dockey) unless append
|
|
28
|
+
# Inserts a hash or array
|
|
29
|
+
if data.is_a?(Hash)
|
|
30
|
+
@@db.pipelined do
|
|
31
|
+
data.each do |key,value|
|
|
32
|
+
raise ArgumentError, "Invalid value object: #{value.inspect}. Hash is expected." unless value.is_a?(Hash)
|
|
33
|
+
value.each do |attrib,value|
|
|
34
|
+
unless _is_reserved?(attrib,value)
|
|
35
|
+
@@db.sadd(dockey,setelement(key,attrib,value))
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
else
|
|
41
|
+
@@db.pipelined do
|
|
42
|
+
data.each do |value|
|
|
43
|
+
@@db.sadd(dockey,value)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
true
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Adds a simple key/value pair
|
|
52
|
+
def put_value(dockey,value)
|
|
53
|
+
if dockey
|
|
54
|
+
@@db.del(dockey)
|
|
55
|
+
@@db.set(dockey,value.to_s) if value
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Retrieves value for a given key
|
|
60
|
+
def get_value(dockey)
|
|
61
|
+
@@db.get(dockey) if dockey
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def incr(dockey)
|
|
65
|
+
@@db.incr(dockey)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def decr(dockey)
|
|
69
|
+
@@db.decr(dockey)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Retrieves set for given dockey,source,user
|
|
73
|
+
def get_data(dockey,type=Hash)
|
|
74
|
+
res = type == Hash ? {} : []
|
|
75
|
+
if dockey
|
|
76
|
+
members = @@db.smembers(dockey)
|
|
77
|
+
members.each do |element|
|
|
78
|
+
if type == Hash
|
|
79
|
+
key,attrib,value = getelement(element)
|
|
80
|
+
res[key] = {} unless res[key]
|
|
81
|
+
res[key].merge!({attrib => value})
|
|
82
|
+
else
|
|
83
|
+
res << element
|
|
84
|
+
end
|
|
85
|
+
end if members
|
|
86
|
+
res
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# Retrieves diff data hash between two sets
|
|
91
|
+
def get_diff_data(src_dockey,dst_dockey,p_size=nil)
|
|
92
|
+
res = {}
|
|
93
|
+
if src_dockey and dst_dockey
|
|
94
|
+
@@db.sdiff(dst_dockey,src_dockey).each do |element|
|
|
95
|
+
key,attrib,value = getelement(element)
|
|
96
|
+
res[key] = {} unless res[key]
|
|
97
|
+
res[key].merge!({attrib => value})
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
if p_size
|
|
101
|
+
diff = {}
|
|
102
|
+
page_size = p_size
|
|
103
|
+
res.each do |key,item|
|
|
104
|
+
diff[key] = item
|
|
105
|
+
page_size -= 1
|
|
106
|
+
break if page_size <= 0
|
|
107
|
+
end
|
|
108
|
+
[diff,res.size]
|
|
109
|
+
else
|
|
110
|
+
[res,res.size]
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# Deletes data from a given doctype,source,user
|
|
115
|
+
def delete_data(dockey,data={})
|
|
116
|
+
if dockey and data
|
|
117
|
+
@@db.pipelined do
|
|
118
|
+
data.each do |key,value|
|
|
119
|
+
value.each do |attrib,val|
|
|
120
|
+
@@db.srem(dockey,setelement(key,attrib,val))
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
true
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
# Deletes all keys matching a given mask
|
|
129
|
+
def flash_data(keymask)
|
|
130
|
+
@@db.keys(keymask).each do |key|
|
|
131
|
+
@@db.del(key)
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
# Returns array of keys matching a given keymask
|
|
136
|
+
def get_keys(keymask)
|
|
137
|
+
@@db.keys(keymask)
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
# Returns true if given item is a member of the given set
|
|
141
|
+
def ismember?(setkey,item)
|
|
142
|
+
@@db.sismember(setkey,item)
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
# Lock a given key and release when provided block is finished
|
|
146
|
+
def lock(dockey,timeout=0,raise_on_expire=false)
|
|
147
|
+
m_lock = get_lock(dockey,timeout,raise_on_expire)
|
|
148
|
+
res = yield
|
|
149
|
+
release_lock(dockey,m_lock)
|
|
150
|
+
res
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def get_lock(dockey,timeout=0,raise_on_expire=false)
|
|
154
|
+
lock_key = _lock_key(dockey)
|
|
155
|
+
current_time = Time.now.to_i
|
|
156
|
+
ts = current_time+(Rhoconnect.lock_duration || timeout)+1
|
|
157
|
+
loop do
|
|
158
|
+
if not @@db.setnx(lock_key,ts)
|
|
159
|
+
if raise_on_expire or Rhoconnect.raise_on_expired_lock
|
|
160
|
+
if @@db.get(lock_key).to_i <= current_time
|
|
161
|
+
# lock expired before operation which set it up completed
|
|
162
|
+
# this process cannot continue without corrupting locked data
|
|
163
|
+
raise StoreLockException, "Lock \"#{lock_key}\" expired before it was released"
|
|
164
|
+
end
|
|
165
|
+
else
|
|
166
|
+
if @@db.get(lock_key).to_i <= current_time and
|
|
167
|
+
@@db.getset(lock_key,ts).to_i <= current_time
|
|
168
|
+
# previous lock expired and we replaced it with our own
|
|
169
|
+
break
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
sleep(1)
|
|
173
|
+
current_time = Time.now.to_i
|
|
174
|
+
else
|
|
175
|
+
break #no lock was set, so we set ours and leaving
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
return ts
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
# Due to redis bug #140, setnx always returns true so this doesn't work
|
|
182
|
+
# def get_lock(dockey,timeout=0)
|
|
183
|
+
# lock_key = _lock_key(dockey)
|
|
184
|
+
# until @@db.setnx(lock_key,1) do
|
|
185
|
+
# sleep(1)
|
|
186
|
+
# end
|
|
187
|
+
# @@db.expire(lock_key,timeout+1)
|
|
188
|
+
# Time.now.to_i+timeout+1
|
|
189
|
+
# end
|
|
190
|
+
|
|
191
|
+
def release_lock(dockey,lock)
|
|
192
|
+
@@db.del(_lock_key(dockey)) if (lock >= Time.now.to_i)
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
# Create a copy of srckey in dstkey
|
|
196
|
+
def clone(srckey,dstkey)
|
|
197
|
+
@@db.sdiffstore(dstkey,srckey,'')
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
# Rename srckey to dstkey
|
|
201
|
+
def rename(srckey,dstkey)
|
|
202
|
+
@@db.rename(srckey,dstkey) if @@db.exists(srckey)
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
alias_method :set_value, :put_value
|
|
206
|
+
alias_method :set_data, :put_data
|
|
207
|
+
|
|
208
|
+
private
|
|
209
|
+
def _get_redis(server=nil)
|
|
210
|
+
if ENV[REDIS_URL]
|
|
211
|
+
Redis.connect(:url => ENV[REDIS_URL])
|
|
212
|
+
elsif server and server.is_a?(String)
|
|
213
|
+
host,port,db,password = server.split(':')
|
|
214
|
+
Redis.new(:thread_safe => true, :host => host,
|
|
215
|
+
:port => port, :db => db, :password => password)
|
|
216
|
+
elsif server and server.is_a?(Redis)
|
|
217
|
+
server
|
|
218
|
+
else
|
|
219
|
+
Redis.new(:thread_safe => true)
|
|
220
|
+
end
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
def _lock_key(dockey)
|
|
224
|
+
"lock:#{dockey}"
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
def _is_reserved?(attrib,value) #:nodoc:
|
|
228
|
+
RESERVED_ATTRIB_NAMES.include? attrib
|
|
229
|
+
end
|
|
230
|
+
end
|
|
231
|
+
end
|
|
232
|
+
end
|