rhoconnect 3.0.6 → 3.1.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. data/CHANGELOG.md +9 -0
  2. data/Gemfile +3 -3
  3. data/Gemfile.lock +38 -17
  4. data/Rakefile +0 -10
  5. data/bench/benchapp/Gemfile.lock +1 -0
  6. data/bench/distr_bench/distr_bench_main +94 -27
  7. data/bench/distr_bench/run_test_query_script.sh +22 -18
  8. data/bench/lib/bench/aws_utils.rb +326 -0
  9. data/bench/lib/bench/bench_result_processor.rb +268 -75
  10. data/bench/lib/bench/cli.rb +1 -0
  11. data/bench/lib/bench/distr_runner.rb +102 -0
  12. data/bench/lib/bench/utils.rb +127 -0
  13. data/bench/lib/bench.rb +16 -15
  14. data/bench/prepare_bench +3 -11
  15. data/bench/scripts/test_query_script.rb +6 -7
  16. data/bin/rhoconnect-benchmark +257 -5
  17. data/doc/benchmarks-running.txt +140 -0
  18. data/doc/client-java.txt +236 -0
  19. data/doc/client-objc.txt +41 -1
  20. data/doc/client.txt +12 -0
  21. data/doc/command-line.txt +12 -3
  22. data/doc/cud-conflicts.txt +68 -0
  23. data/doc/deploying.txt +1 -70
  24. data/doc/hosting-rhohub.txt +3 -0
  25. data/doc/install.txt +50 -13
  26. data/doc/java-plugin.txt +217 -177
  27. data/doc/net-plugin.txt +97 -64
  28. data/doc/plugin-intro.txt +4 -2
  29. data/doc/preparing-production.txt +63 -0
  30. data/doc/rhoconnect-redis-stack.txt +252 -0
  31. data/doc/source-adapters.txt +3 -1
  32. data/doc/tutorial.txt +111 -49
  33. data/examples/simple/dump.rdb +0 -0
  34. data/installer/unix-like/rho_connect_install_constants.rb +6 -5
  35. data/installer/unix-like/rho_connect_install_installers.rb +6 -2
  36. data/installer/utils/nix_install_test.rb +2 -0
  37. data/installer/utils/package_upload/auto-repo.rb +136 -0
  38. data/installer/utils/package_upload/repos.rake +6 -3
  39. data/installer/utils/package_upload/s3_upload.rb +11 -6
  40. data/installer/windows/rhosync.nsi +5 -5
  41. data/lib/rhoconnect/client_sync.rb +2 -2
  42. data/lib/rhoconnect/document.rb +12 -0
  43. data/lib/rhoconnect/jobs/source_job.rb +2 -2
  44. data/lib/rhoconnect/predefined_adapters/bench_adapter.rb +61 -0
  45. data/lib/rhoconnect/source.rb +5 -0
  46. data/lib/rhoconnect/source_adapter.rb +10 -1
  47. data/lib/rhoconnect/source_sync.rb +161 -88
  48. data/lib/rhoconnect/store.rb +48 -0
  49. data/lib/rhoconnect/test_methods.rb +6 -6
  50. data/lib/rhoconnect/version.rb +1 -1
  51. data/lib/rhoconnect.rb +25 -2
  52. data/spec/apps/rhotestapp/sources/sample_adapter.rb +29 -0
  53. data/spec/jobs/source_job_spec.rb +5 -5
  54. data/spec/source_adapter_spec.rb +10 -0
  55. data/spec/source_sync_spec.rb +114 -33
  56. data/spec/spec_helper.rb +21 -2
  57. data/spec/store_spec.rb +29 -0
  58. data/spec/support/shared_examples.rb +1 -1
  59. data/spec/test_methods_spec.rb +4 -4
  60. data/tasks/redis.rake +2 -2
  61. metadata +59 -59
  62. data/bench/benchapp/log/passenger.3000.log +0 -1
  63. data/bench/benchapp/log/passenger.9292.log +0 -59
  64. data/bench/benchapp/tmp/pids/passenger.3000.pid.lock +0 -0
  65. data/bench/benchapp/tmp/pids/passenger.9292.pid.lock +0 -0
  66. data/bench/lib/testdata/0-data.txt +0 -0
  67. data/bench/lib/testdata/1-data.txt +0 -0
  68. data/bench/lib/testdata/10-data.txt +0 -15
  69. data/bench/lib/testdata/2-data.txt +0 -3
  70. data/bench/lib/testdata/25-data.txt +0 -39
  71. data/bench/lib/testdata/250-data.txt +0 -353
  72. data/bench/lib/testdata/3-data.txt +0 -4
  73. data/bench/lib/testdata/50-data.txt +0 -70
  74. data/bench/lib/testdata/500-data.txt +0 -711
@@ -0,0 +1,140 @@
1
+ Running RhoConnect Benchmarks
2
+ ===
3
+
4
+ ## Introduction
5
+
6
+ You can execute benchmark tests against your deployment and verify the performance of your Rhoconnect application using the provided `rhoconnect-benchmark` command.
7
+ During the test the Rhoconnect benchmark framework will dynamically create a special ephemeral source adapter inside of
8
+ your application and perform the 5-step query use-case mimicking the typical device-to-server communication.
9
+
10
+ Currently, the Rhoconnect Benchmark measures two primary system-wide metrics: Average Time and Throughput.
11
+
12
+ - Average time (milliseconds per request) is calculated as sum_of_executed_http_request_times/number of http requests.
13
+ - Throughput is an integral metric (number of requests per second) calculated as: cumulative_number_of_http_requests_processed/(finish_time_for_last_test - start_time_of_first_test).
14
+
15
+ NOTE: Both metrics implicitly include the network latency and therefore represent the performance of the whole system `device-network-server`.
16
+
17
+ ## Rhoconnect Benchmark Command
18
+
19
+ To execute the Rhoconnect Benchmark test, use the `rhoconnect-benchmark` command. This command has the following options:
20
+
21
+ <table border="1">
22
+ <tr>
23
+ <td width="20">-u</td>
24
+ <td width="200"><code>--url URL</code></td>
25
+ <td>Use URL to specify the targeted Rhoconnect server for benchmarking. If this option is not specified, <code>http://localhost:9292</code> will be used as a default.</td>
26
+ </tr>
27
+ <tr>
28
+ <td width="20">-p</td>
29
+ <td width="200"><code>--payload NUMBER</code></td>
30
+ <td>This options specifies the amount of data to be simulated in the query request (in number of records). Default: 100, which roughly translates into 20 kilobytes.</td>
31
+ </tr>
32
+ <tr>
33
+ <td width="20">-C</td>
34
+ <td width="200"><code>--nclients NUMBER</code></td>
35
+ <td>Specifies how many concurrent clients to emulate during the test. If this option is omitted, then the number of simulated clients will be determined based on the number of available seats in your Rhoconnect application's license.</td>
36
+ </tr>
37
+ <tr>
38
+ <td width="20">-R</td>
39
+ <td width="200"><code>--niterations NUMBER</code></td>
40
+ <td>Specifies how many times each emulated client will perform the test. Default: 10. The more iterations you specify, the more time your test will take, but it will lessen the test result's statistical fluctuations.</td>
41
+ </tr>
42
+ <tr>
43
+ <td width="20">-S</td>
44
+ <td width="200"><code>--save PATH</code></td>
45
+ <td>This option saves the test results in the PATH sub-directory and run the post-processing on the saved files (for example, generate the EXCEL spreadsheet). All the results will be saved under the PATH root directory.</td>
46
+ </tr>
47
+ <tr>
48
+ <td width="20">-x</td>
49
+ <td width="200"><code>--maxpayloadloops NUMBER</code></td>
50
+ <td>This option runs several tests in a loop varying the payload between 1 and NUMBER. The specified interval will be split by 10. For example: -m 500 will produce 10 test executions , first for payload of 1 record, then - for 56, 112, 167, 223, 278, 334, 389, 445, and 500</td>
51
+ </tr>
52
+ <tr>
53
+ <td width="20">-m</td>
54
+ <td width="200"><code>--maxclientloops NUMBER</code></td>
55
+ <td>This option runs several tests in a loop varying number of concurrent clients between 1 and NUMBER. The specified interval will be split by 5. For example: -m 10 will produce 5 test executions , first for 1 client, then - for 3, 6, 8, and 10</td>
56
+ </tr>
57
+ <tr>
58
+ <td width="20">-A</td>
59
+ <td width="200"><code>--advanced</code></td>
60
+ <td>This convenience option combines -m 10, -x 500, and -S <cur_dir/bench_results> - thus running a matrix of tests varying in payload and number of concurrent clients. Also, it saves the results into the `bench_results` subdirectory and runs the available post-processing.</td>
61
+ </tr>
62
+ <tr>
63
+ <td width="20">-D</td>
64
+ <td width="200"><code>--distributed AWSFILE</code></td>
65
+ <td>This option executes the advanced benchmark test using the remote AWS EC2 clients. Currently, this option is only available for the Linux/MacOS machines. See Distributed Benchmark section below for details.</td>
66
+ </tr>
67
+ </table>
68
+
69
+ ## Result post-processing
70
+ By default, all results are displayed in the console during the test. However, it is possible to save all the results into the file and, additionally, generate the EXCEL files and/or PNG images using the `--save PATH` option. The results are saved for two benchmark metrics: Average Time and Throughput.
71
+
72
+ ### Generate EXCEL spreadsheet
73
+ To enable the automatic generation of the EXCEL spreadsheets from the test results, please install the `spreadsheet` gem by using:
74
+
75
+ $ [sudo] gem install spreadsheet
76
+
77
+ You can read more about the `spreadsheet` gem [here](http://rubygems.org/gems/spreadsheet).
78
+
79
+ ### Generate PNG images
80
+ To enable the automatic generation of the PNG images from the test results, install the `gruff` gem.
81
+ Installation of the GRUFF gem requires an additional installation of several components.
82
+ Use [this](http://nubyonrails.com/pages/gruff) guide to install the GRUFF on your machine.
83
+
84
+ ## Distributed Benchmark test
85
+ To fully simulate the distributed nature of the device-to-server system, the Rhoconnect Benchmark command allows to you to create distributed clients through the [AWS Cloud Formation](http://aws.amazon.com/cloudformation/).
86
+
87
+ NOTE: Distributed Rhoconnect Benchmark test will be executed via the AWS Cloud Formation and EC2 services using your account and therefore you will be billed for its usage by Amazon.
88
+
89
+ In order to run the distributed Benchmark test, you need to have an AWS account and specify its settings in a YAML file, which should have the following structure:
90
+
91
+ :::ruby
92
+ :default:
93
+ :region: desired_aws_region
94
+ :aws_access_key_id: your_aws_account_key_id
95
+ :aws_secret_access_key: your_aws_account_secret_access_key
96
+ :aws_key_pair_name: your_aws_ec2_security_key_pair
97
+ :aws_ssh_pem_file: location_of_your_aws_ssh_pem_file
98
+
99
+ Here is the description of each entry in the AWS settings file:
100
+
101
+ <table border="1">
102
+ <tr>
103
+ <td width="300"><code>:region</code></td>
104
+ <td>Specify the desired AWS region for your EC2 clients. Default is 'us-west-1'. Typically, you need to specify the same region as the location of your Rhoconnect server to minimize the network impact (since communications between different regions will take more time).</td>
105
+ </tr>
106
+ <tr>
107
+ <td width="200"><code>:aws_access_key_id</code></td>
108
+ <td>Your AWS access key ID.</td>
109
+ </tr>
110
+ <tr>
111
+ <td width="200"><code>:aws_secret_access_key</code></td>
112
+ <td>Your AWS secret access key.</td>
113
+ </tr>
114
+ <tr>
115
+ <td width="200"><code>:aws_key_pair_name</code></td>
116
+ <td>In order to create EC2 clients, you will need to create EC2 KeyPair in the desired region. After that KeyPair is created, you will have its name, which should be specified here.</td>
117
+ </tr>
118
+ <tr>
119
+ <td width="200"><code>:aws_ssh_pem_file</code></td>
120
+ <td>For the above KeyPair, you will have the corresponding keypair .PEM file. Download this file to your machine and reference its location here.</td>
121
+ </tr>
122
+ </table>
123
+
124
+ Once the AWS settings file is created, you need to make sure that the following gems are installed on your machine:
125
+
126
+ - fog
127
+ - net-ssh-multi
128
+
129
+ You can install those gems using the `[sudo] gem install <gemname>` command.
130
+
131
+ Once all the pre-requisites are met, you can run the distributed Rhoconnect Benchmark test with the following command:
132
+
133
+ $ rhoconnect-benchmark -u `server_url` -D `path_to_aws_settings_file`
134
+
135
+
136
+ NOTE: In order to run the distributed Benchmark test, you must provide public server's URL accessible from the outside clients.
137
+
138
+
139
+
140
+
@@ -0,0 +1,236 @@
1
+ # Android Java Client
2
+
3
+ ## Getting started
4
+
5
+ * The RhoConnect Client is part of the Rhodes repository. You can get it [on github](https://github.com/rhomobile/rhodes/downloads) (select the latest 'rhoconnect-client' package).
6
+
7
+ * The RhoConnect Client for Android contains two files:
8
+
9
+ ** rhoimpl.jar - Java part of RhoConnect Client library
10
+
11
+ ** librhoconnectclient.so - native part of RhoConnect Client library
12
+
13
+ These can be build from <rhodes>/rhoconnect-client directory with next command
14
+
15
+ :::shell
16
+ $>rake android:default
17
+
18
+ * Create new Android project or open existing one in Eclipse. Add rhoimple.jar to your project build path and copy librhoconnectclient.so to <project_root>/libs/armeabi, so both Java and native parts of RhoConnect Client library will link with your project.
19
+
20
+ * Copy all files and subfolders from <rhodes>/rhoconnect-client/Java/RhoConnect/assets to assets folder of your Android project.
21
+
22
+ ## RhoConnectClient initialization
23
+
24
+ * Load native library before any RhoConnect client usage. Example of appropriate place to do so is Android application's onCreate method
25
+
26
+ :::java
27
+
28
+ import android.app.Application;
29
+ public class SampleApplication extends Application
30
+ {
31
+ public void onCreate() {
32
+ System.loadLibrary("rhoconnectclient");
33
+ }
34
+ }
35
+
36
+ * Configure and initialize RhoConnect library. Example of appropriate place to do so is main Activity onCreate method
37
+
38
+ * Login to RhoConnect server
39
+
40
+ :::cplusplus
41
+ public void onCreate(Bundle savedInstanceState) {
42
+ super.onCreate(savedInstanceState);
43
+ setContentView(R.layout.main);
44
+
45
+ ApplicationInfo appInfo = getApplicationInfo();
46
+
47
+ try {
48
+ RhoFileApi.initRootPath(appInfo.dataDir, appInfo.sourceDir);
49
+ RhoFileApi.init(this.getApplicationContext());
50
+
51
+ RhoLogConf.setMinSeverity(0);
52
+ RhoLogConf.setEnabledCategories("*");
53
+
54
+ RhoConnectClient.nativeInit();
55
+ } catch (Exception e) {
56
+ Logger.E(TAG, e.getMessage());
57
+ }
58
+ mSyncClient = new RhoConnectClient();
59
+ mModels = new RhomModel[]{
60
+ new RhomModel("Customer", RhomModel.SYNC_TYPE_INCREMENTAL),
61
+ new RhomModel("Product", RhomModel.SYNC_TYPE_INCREMENTAL)
62
+ };
63
+ mSyncClient.initialize(mModels);
64
+ mSyncClient.setPollInterval(0);
65
+ mSyncClient.setSyncServer("http://rhodes-store-server.heroku.com/application");
66
+ mSyncClient.setBulkSyncState(1);
67
+ mSyncClient.loginWithUserAsync("", "", new RhoConnectNotify.IDelegate() {
68
+ public void call(RhoConnectNotify notify) { onLogin(notify); } });
69
+ }
70
+ public void onLogin(RhoConnectNotify notify) {
71
+ // Handle login event
72
+ }
73
+
74
+ Note: RhoConnect callbacks (like passed to RhoConnectClient.loginWithUserAsync methodin axample above) may and most possibly will be called from another thread. It is up to application developer to care about synchronizing or forwarding call to an appropriate thread like GUI thread or Service thread.
75
+
76
+ ## Object Model
77
+
78
+ ### Intro
79
+
80
+ RhoConnect Client Android Java API resides at com.rhomobile.rhoconnect pakage. It contains two main classes: RhoConnectClient and RhomModel. The package also contains two classes which represent results of call to the API. These are RhoConnectNotify and RhoConnectObjectNotify.
81
+ Also several utility classes from com.rhomobile.rhodes package can be used. These are RhoConf, RhoLogConf, Logger.
82
+
83
+ ### RhoConnectClient
84
+
85
+ :::cplusplus
86
+ package com.rhomobile.rhoconnect;
87
+ public class RhoConnectClient{
88
+ /// Call this method before create and use the client. It sets up directory structure and makes nessesary native library initialization.
89
+ public static native void nativeInit();
90
+ /// Creates instance of RhoConnectClient singlethon (yes, it's only one instance of RhoConnectClient allowed).
91
+ public RhoConnectClient();
92
+ /// Call this method to close network connections and release any resources gracefully
93
+ public synchronized void close();
94
+ /// Makes db models initialization. This call must be made just after RhoConnectClient construction and before any other calls to RhoConnectClient object.
95
+ public native void initialize(RhomModel models[]);
96
+ /// Sets up server URL to sync (RhoConnect server)
97
+ public native void setSyncServer(String url);
98
+ /// Forces synchronous or asynchronous RhoConnectClient mode
99
+ /// true - asynchronous mode (default)
100
+ /// false - synchronous mode
101
+ public native void setThreadedMode(boolean mode);
102
+ /// Sets/gets auto sync interval. 0 - disable auto sync
103
+ public native void setPollInterval(int interval);
104
+ public native int getPollInterval();
105
+ ///
106
+ public native void setBulkSyncState(int state);
107
+ public native int getBulkSyncState();
108
+ /// Set get various configuration parameters.
109
+ public native void setConfigString(String name, String param);
110
+ public native String getConfigString(String name);
111
+ /// Reset all data for all models in local database, also perform logout
112
+ public native void databaseFullResetAndLogout();
113
+ /// Checks does login session exists in the database
114
+ public native boolean isLoggedIn();
115
+ /// Logins to RhoConnect server and keep login session in database
116
+ public native RhoConnectNotify loginWithUserSync(String user, String pass);
117
+ /// Logins to RhoConnect server and keep login session in database.
118
+ /// callback will be called when operation has finished.
119
+ public native void loginWithUserAsync(String user, String pass, RhoConnectNotify.IDelegate callback);
120
+ /// Runs sync of all models
121
+ public native RhoConnectNotify syncAll();
122
+ }
123
+
124
+ ### RhomModel
125
+
126
+ :::cplusplus
127
+ package com.rhomobile.rhoconnect;
128
+ public class RhomModel {
129
+ /// Possible model types
130
+ public final static int MODEL_TYPE_PROPERTY_BAG = 0;
131
+ public final static int MODEL_TYPE_FIXED_SCHEMA = 1;
132
+ /// Possible sync types
133
+ public final static int SYNC_TYPE_NONE = 0;
134
+ public final static int SYNC_TYPE_INCREMENTAL = 1;
135
+ public final static int SYNC_TYPE_BULK_ONLY = 2;
136
+ /// Constructor
137
+ public RhomModel(String name, int syncType);
138
+ /// Returns the model name
139
+ public String getName() { return mName; }
140
+ /// Returns the model type
141
+ public int getModelType() { return mModelType; }
142
+ /// Sets the model type
143
+ public void setModelType(int type) { mModelType = type; }
144
+ // Returns the model sync type
145
+ public int getSyncType() { return mSyncType; }
146
+ /// Sets the model sync type
147
+ public void setSyncType(int type) { mSyncType = type; }
148
+ /// Returns the model sync priority
149
+ public int getSyncPriority() { return mSyncPriority; }
150
+ /// Sets the model sync priority
151
+ public void setSyncPriority(int prio) { mSyncPriority = prio; }
152
+ /// Returns the model partition
153
+ public String getPartition() { return mPartition; }
154
+ /// Sets the model partition
155
+ public void setPartition(String part) { mPartition = part; }
156
+ /// Runs sync of the model
157
+ public RhoConnectNotify sync();
158
+ /// Creates model object with properties and save to database, object id will be generated automatically if not set
159
+ public void create(Map<String, String> props);
160
+ /// Finds object by object id
161
+ public Map<String, String> find(String objectId)
162
+ /// Saves changes to existing object
163
+ public void save(Map<String, String> item);
164
+ /// Destroys existing object
165
+ public void destroy(Map<String, String> item) {
166
+
167
+ // Returns first object which matches the condition
168
+ public Map<String, String> findFirst(Map<String, String> condition);
169
+ // Returns all objects which matched the condition
170
+ public Collection<Map<String, String> > findAll(Map<String, String> condition);
171
+
172
+ public void startBulkUpdate();
173
+ public void stopBulkUpdate();
174
+ }
175
+
176
+ #### RhoConnectNotify
177
+
178
+ :::cplusplus
179
+ package com.rhomobile.rhoconnect;
180
+ public class RhoConnectNotify {
181
+ public int getTotalCount() { return mTotalCount; }
182
+ public int getProcessedCount() { return mProcessedCount; }
183
+ public int getCumulativeCount() { return mCumulativeCount; }
184
+ public int getSourceId() { return mSourceId; }
185
+ public int getErrorCode() { return mErrorCode; }
186
+ public String getSourceName() { return mSourceName; }
187
+ public String getStatus() { return mStatus; }
188
+ public String getSyncType() { return mSyncType; }
189
+ public String getErrorMessage()
190
+ public String getCallbackParams() { return mParams; }
191
+ /// Developer need to implement and pass reference to this interface
192
+ /// in order to get call back when asynchronous operation has completed
193
+ public static interface IDelegate {
194
+ public void call(RhoConnectNotify notify);
195
+ }
196
+ }
197
+
198
+ #### RhoConnectObjectNotyfy
199
+
200
+ :::cplusplus
201
+ package com.rhomobile.rhoconnect;
202
+ public interface RhoConnectObjectNotify {
203
+ public String[] getDeletedObjects();
204
+ public String[] getUpdatedObjects();
205
+ public String[] getCreatedObjects();
206
+
207
+ public int[] getDeletedSourceIds();
208
+ public int[] getUpdatedSourceIds();
209
+ public int[] getCreatedSourceIds();
210
+
211
+ /// Developer need to implement and pass reference to this interface
212
+ /// in order to get call back when objects are created, updated or destroyed at sync server
213
+ public static interface IDelegate {
214
+ public void call(RhoConnectObjectNotify notify);
215
+ }
216
+ }
217
+
218
+ ### Samples
219
+
220
+ * See android_store sample [rhoconnect-client\Samples\Java\android_store](http://github.com/rhomobile/rhodes/tree/master/rhoconnect-client/Samples/Java/android_store/) as an example.
221
+ * See android test Eclipse project [rhoconnect-client\Java\Android\test](http://github.com/rhomobile/rhodes/tree/master/rhoconnect-client/Java/Android/test/) as another example.
222
+
223
+ ## Packaging RhoConnect Client
224
+ To package the RhoConnect Client archive for distribution, go to the top of the rhodes repository and run:
225
+
226
+ :::term
227
+ $ rake build:rhoconnect_client
228
+
229
+ This will produce a zipfile in the folder called `rhoconnect-client-<someversion>.zip` where `<someversion>` is the version of the client.
230
+
231
+ ## Release procedure
232
+ 1. Unzip package to some folder
233
+
234
+ 2. Open project `rhoconnect-client\ObjectiveC\Tests\RhoConnectClientTest` in xcode and run. See log - SUCCESS should be at the end of log
235
+
236
+ 3. Open project `rhoconnect-client\Samples\ObjectiveC\store` in xcode and run. Press Login, you should see several items, click on item, you should see details
data/doc/client-objc.txt CHANGED
@@ -146,7 +146,8 @@ Here is the Store code for the initialization process, contained in RhoConnectEn
146
146
 
147
147
  sclient.sync_server = @"http://rhodes-store-server.heroku.com/application";
148
148
  sclient.threaded_mode = TRUE;
149
-
149
+ sclient.log_severity = 1;
150
+
150
151
  loginState = [sclient is_logged_in] ? logged_in : logged_out;
151
152
  }
152
153
  return sharedInst;
@@ -190,6 +191,13 @@ Call the RhoConnectClient setNotification method to call a callback method that
190
191
  :::cplusplus
191
192
  [ [RhoConnectEngine sharedInstance].syncClient setNotification: @selector(syncAllComplete:) target:self];
192
193
 
194
+ To perform a bulk sync *bulksync_state* configuration flag should be reset to zero. If you don't need bulk sync then just skip it.
195
+
196
+ :::cplusplus
197
+ // set configuration for bulk sync, it means "next sync should be performed as bulk"
198
+ [RhoConnectEngine sharedInstance].syncClient.bulksync_state = 0;
199
+ // after sync performed the it should contain value 1.
200
+
193
201
  Call a sync method, such as the RhoConnectClient syncAll method or the RhomModel sync method, to sync your client model data with the RhoConnect server.
194
202
 
195
203
  :::cplusplus
@@ -391,6 +399,7 @@ The RhoConnectClient class contains the following properties and methods to buil
391
399
 
392
400
  * <a href="#threaded_mode">threaded_mode property</a>
393
401
  * <a href="#poll_interval">poll_interval property</a>
402
+ * <a href="#log_severity">log_severity property</a>
394
403
  * <a href="#sync_server">sync_server property</a>
395
404
  * <a href="#initDatabase">initDatabase</a>
396
405
  * <a href="#addModels">addModels</a>
@@ -403,6 +412,8 @@ The RhoConnectClient class contains the following properties and methods to buil
403
412
  * <a href="#clearNotification">clearNotification</a>
404
413
  * <a href="#is_logged_in">is\_logged\_in</a>
405
414
  * <a href="#syncAll">syncAll</a>
415
+ * <a href="#is_syncing">is_syncing</a>
416
+ * <a href="#stop_sync">stop_sync</a>
406
417
  * <a href="#search">search</a>
407
418
  * <a href="#setObjectNotification">setObjectNotification</a>
408
419
  * <a href="#clearObjectNotification">clearObjectNotification</a>
@@ -425,6 +436,13 @@ int. Not yet supported. Default = 0.
425
436
  :::cplusplus
426
437
  @property(setter=setPollInterval) int poll_interval;
427
438
 
439
+ ### <a id="log_severity"></a>log\_severity property
440
+
441
+ int. Set minimal severity level for messages to log output. Default = 0.
442
+
443
+ :::cplusplus
444
+ @property(setter=setLogSeverity) int log_severity;
445
+
428
446
  ### <a id="sync_server"></a>sync\_server property
429
447
 
430
448
  NSString. Sets the RhoConnect server url, for example: "`http://<ip>:<port>/application`"
@@ -542,6 +560,20 @@ Instance method. Returns a RhoConnectNotify object after running a sync on all t
542
560
  :::cplusplus
543
561
  - (RhoConnectNotify*) syncAll;
544
562
 
563
+ ### <a id="is_syncing">is_syncing
564
+
565
+ Instance method. Returns TRUE if syncronization is in progress
566
+
567
+ :::cplusplus
568
+ - (BOOL) is_syncing;
569
+
570
+ ### <a id="stop_sync">stop_sync
571
+
572
+ Instance method. Stop current sync if running
573
+
574
+ :::cplusplus
575
+ - (void) stop_sync;
576
+
545
577
  ### <a id="search">search
546
578
 
547
579
  Instance method. Returns a RhoConnectNotify object after sending a search request to the RhoConnect server.
@@ -717,6 +749,7 @@ The RhomModel class contains the following properties and methods for setting an
717
749
  * <a href="#destroy">destroy</a>
718
750
  * <a href="#startBulkUpdate">startBulkUpdate</a>
719
751
  * <a href="#stopBulkUpdate">stopBulkUpdate</a>
752
+ * <a href="#is_changed">is_changed</a>
720
753
 
721
754
  ### <a id="name"></a>name property
722
755
 
@@ -924,6 +957,13 @@ Run this method when you start to create or update a bunch of models; it will op
924
957
  :::cplusplus
925
958
  - (void) stopBulkUpdate;
926
959
 
960
+ ### <a id="is_changed">is_changed
961
+
962
+ Check does model contain non-synced local changes
963
+
964
+ :::cplusplus
965
+ - (BOOL) is_changed;
966
+
927
967
  ## RhoConnectNotify Class API
928
968
 
929
969
  Several RhoConnectClient methods return a RhoConnectNotify object. The properties for the RhoConnectNotify class provide access to sync notification objects as described [here](/rhodes/synchronization#notifications). (Developers do not set RhoConnectNotify properties, but only read them after a call to a RhoConnectClient method that returns a RhoConnectNotify object.)
data/doc/client.txt CHANGED
@@ -43,6 +43,9 @@ Rhoconnect Client is a library to add sync data capability to your applications.
43
43
  //default is 0. Not supported yet
44
44
  @property(setter=setPollInterval) int poll_interval;
45
45
 
46
+ //default is 0. Set minimal severity level for messages to log output
47
+ @property(setter=setLogSeverity) int log_severity;
48
+
46
49
  //set rhoconnect server url, for example: "http://<ip>:<port>/application"
47
50
  @property(assign, setter=setSyncServer) NSString* sync_server;
48
51
 
@@ -74,6 +77,12 @@ Rhoconnect Client is a library to add sync data capability to your applications.
74
77
  // run sync of all models
75
78
  - (RhoConnectNotify*) syncAll;
76
79
 
80
+ // check is sync is in progress
81
+ - (BOOL) is_syncing;
82
+
83
+ //stop current sync if running
84
+ - (void) stop_sync;
85
+
77
86
  //send search request to rhoconnect
78
87
  - (RhoConnectNotify*) search: (NSArray*)models from: (NSString*) from params: (NSString*)params sync_changes: (BOOL)
79
88
  sync_changes progress_step: (int) progress_step;
@@ -148,6 +157,9 @@ Rhoconnect Client is a library to add sync data capability to your applications.
148
157
  //these are equivalent to start/commit transaction
149
158
  - (void) startBulkUpdate;
150
159
  - (void) stopBulkUpdate;
160
+
161
+ //check does model was modified and not yet synced
162
+ - (BOOL) is_changed;
151
163
 
152
164
  #### RhoConnectNotify
153
165
 
data/doc/command-line.txt CHANGED
@@ -61,7 +61,9 @@ After generating the application, you might be asked to change directories to yo
61
61
 
62
62
  ### Add a New Source Adapter
63
63
 
64
- To generate a source for your RhoConnect application, run the `rhoconnect source` command within your application directory:
64
+ To generate a source for your RhoConnect application, you can run the `rhoconnect source` command within your application directory.
65
+
66
+ **NOTE:** You can also write the source into your backend application and [write a RhoConnect plugin](/rhoconnect/plugin-intro) in Java, .NET, or other language for that application.
65
67
 
66
68
  :::term
67
69
  Usage: rhoconnect source name [options] [args]
@@ -69,7 +71,7 @@ To generate a source for your RhoConnect application, run the `rhoconnect source
69
71
  Generates a new source adapter.
70
72
 
71
73
  Required:
72
- name - source name(i.e. product)
74
+ name - the source name(i.e. product)
73
75
 
74
76
 
75
77
  Options specific for this generator:
@@ -215,4 +217,11 @@ Here is a complete list of the rake tasks available in a RhoConnect application:
215
217
  rake rhoconnect:start # Start rhoconnect server
216
218
  rake rhoconnect:stop # Stop rhoconnect server
217
219
  rake rhoconnect:war # Build executable WAR file to be used in Java App Servers
218
- rake rhoconnect:web # Launch the web console in a browser - uses :syncserver: in settings.yml
220
+ rake rhoconnect:web # Launch the web console in a browser - uses :syncserver: in settings.yml
221
+
222
+ ## Generate Source
223
+
224
+ Connecting to a backend service with RhoConnect requires that you write a small amount of code for the query, create, update and delete operations of your particular enterprise backend. The collection of the code for these operations is called a source. To generate source for your RhoConnect application:
225
+
226
+ * Generate a Ruby code [RhoConnect source adapter](/rhoconnect/source-adapters).
227
+ * Write the source code (the query, create, update and delete operations) into your backend application and [write a RhoConnect plugin](/rhoconnect/plugin-intro) in the language that matchs your backend application, such as Java or .NET.
@@ -0,0 +1,68 @@
1
+ Resolving CUD conflicts
2
+ ===
3
+
4
+ Rhoconnect CUD queue and potential conflicts
5
+ ---
6
+
7
+ By design, your Rhoconnect application supports parallel dispatching of the multiple client's requests via the asynchronous Resque jobs. This scenario can lead to a situation where two or more clients will try to perform CUD operations at the same time, potentially creating the race condition. For example, this can happen when two users will try to insert or delete the same record simultaneously.
8
+ To handle this situation , Rhoconnect uses the CUD queue, which is being dispatched continuously. You can inspect this queue before the CUD operation is called and mark the conflicting records for special processing. To do this, you need to override the Source Adapter `validate` method that is called before the CUD queue is dispatched. This method has the following parameters:
9
+
10
+ <table border="1">
11
+ <tr>
12
+ <td>String</td>
13
+ <td><code>operation</code></td>
14
+ <td>CUD operation marker, one of three: create, update, or delete</td>
15
+ </tr>
16
+ <tr>
17
+ <td>Array Of Record Hashes</td>
18
+ <td><code>cud_queue</code></td>
19
+ <td>CUD queue consisting of CUD request hashes, ordered from oldest to newest. Each entry in the queue contains a hash of CUD records to process. (Each CUD client request can contain more than one record</td>
20
+ </tr>
21
+ <tr>
22
+ <td>Array Of Client Ids</td>
23
+ <td><code>client_queue</code></td>
24
+ <td>This array is used to map the CUD request in the above queue to a corresponding client ID. i.e. CUD_queue[N] request was issued by client_queue[N] client. Please note that there may be several entries from the same client - if they came separately in time</td>
25
+ </tr>
26
+ </table>
27
+
28
+ Below you can see the example of the `validate` method parameters indicating two create requests containing the conflicting records:
29
+
30
+ :::ruby
31
+ client_1 = 'cid_1'
32
+ cud_request_1 = { 'temp_cid1_1' => {'name' => 'iPhone'}, 'temp_cid1_2' => {'name' => 'Android'}}
33
+ client_2 = 'cid_2'
34
+ cud_request_2 = { 'temp_cid2_1' => {'name' => 'iPhone'}} # this record seems to be the duplicate of the record 'temp_cid1_1'
35
+
36
+ operation = 'create'
37
+ cud_queue = [ cud_request_1, cud_request_2 ]
38
+ client_ids = [ client_1, client_2 ]
39
+
40
+ Detecting the conflict and forcing an error
41
+ ---
42
+
43
+ Using the above `validate` method you can iterate through the queue and detect CUD conflicts based on the desired application logic. Once the conflicting record is found (for example, duplicate create request), you need to mark it by inserting the conflicting record parameters into the special hash structure that is returned by the `validate` method:
44
+
45
+ :::ruby
46
+ def validate(operation, cud_queue, client_ids)
47
+ resulting_meta_hash = {}
48
+
49
+ # iterating through the queue
50
+ cud_queue.each_with_index do |cud_request, index|
51
+ cud_request_client = client_ids[index]
52
+
53
+ # iterating through the request records
54
+ cud_request.each do |record_id, record_hash|
55
+ # ... detecting the conflict here ....
56
+ # !!! found a conflict - force an error
57
+ error_record_id = record_id
58
+ record_meta_data = { error_record_id => { :error => 'my_error_string: conflict is detected!!!' }}
59
+ resulting_meta_hash[index] ||= {}
60
+ resulting_meta_hash[index].merge!(record_meta_data)
61
+ end
62
+ end
63
+
64
+ resulting_meta_hash
65
+ end
66
+
67
+ Once the `validate` method returns non-empty validation metadata hash structure, it will be used in processing the CUD queue. All marked records will not be processed, but instead an error will be sent back to the originating client with the user-provided error message.
68
+