electrode-io / electrode-ota-server

Electrode Over The Air Server for hot deployment of React Native and Cordova mobile apps
Other
204 stars 40 forks source link

updateCheck method generate same packageHash against different release packages #129

Open w000xj opened 4 years ago

w000xj commented 4 years ago

We are using the electrode-ota-server in our production environment as self-hosted code-push server, while there are pretty much errors recently saying: upload error { Error: ER_DUP_ENTRY: Duplicate entry '90709eb9e55eafbea67271dad5df0be00dba4c811041bd428442a47c2bc0a68b' for key 'PRIMARY'.

So I picked one of the updateCheck request that produced the error, then debugged on our server and find out: Say the client-installed-package is label v62, the latest version is v68, when the client call CodePush.sync() doing updateCheck, the error occurs, then I release a v69 update, call updateCheck, this error still occurs. image According to this piece of code ,no matter what the client-installed-package is, say v62 and v67, the zipfile in the code will always contain the latest published package, thus the same deltaResults delivered to the upload method. So after I published a code-push release v69, client v67 call updateCheck, insert package_content, package_diff, everything is ok, then client v62 call updateCheck and find there is no record match v69 and v62 in the package_diff, moving on execute the same code as v67, until the upload method which insert the same package into package_content as v67 updateCheck does, the error appears.

ps: v62, v67, v69 is the label of code-push release containing only one jsbundle file.

Is this a bug? or I just missed something?

need help

scrajesh commented 4 years ago

for every version the difference will be significant and obviously the deltaResults has to be different, ain't it? but in your case are you meaning the the publishing version doesn't have that significant difference?

w000xj commented 4 years ago

for every version the difference will be significant

Yes, it is, every publishing version is different from each other.

But according to the delta function, deltaResults mean to be same between v62 vs v69 and v67 vs v69, actually it does when I debugged on my server.

  1. release a code-push update v4
  2. client with v3 find package v4 and update
  3. client with v2 find package v4 and update

step 3 will reproduce this issue , I think it's a common problem, not just in my case.

scrajesh commented 4 years ago

Did you had code changes between your versions? or was it more of config changes? Am trying to understand and reproduce the same scenario, so far am not successful in it.. your inputs might help..

scrajesh commented 4 years ago

Can you try reproducing the same with a minimal setup of an app?

You can use this sample app: https://github.com/scrajesh/CodePushDemoApp

I can reuse the same setup to further investigate the issue.

w000xj commented 4 years ago

react-native-code-push version is not specified in the demo, which version shall I use?

scrajesh commented 4 years ago

I use this "react-native-code-push": "^6.0.0" locally.

w000xj commented 4 years ago

Reproduced the error with your demo either, node version is v10.17.0. change dependencies to "dependencies": { "react": "16.8.3", "react-native": "0.59.8", "react-native-code-push": "5.5.2" },

  1. Install the apk generated by your demo in two android phone A and B.
  2. Modify App.js, release a code-push update containing only a jsbundle file, say label v4.
  3. Open the app in phone A and phone B press Press for dialog-driven sync on both.(ok)
  4. Modify App.js, release a code-push update containing only a jsbundle file, say label v5.
  5. In phone B press Press for dialog-driven sync.(ok)
  6. Modify App.js, release a code-push update containing only a jsbundle file, say label v6.
  7. In phone B press Press for dialog-driven sync.(ok)
    Now I have phone A updated with label v4 and phone B updated with label v6
  8. In phone A press Press for dialog-driven sync.(error)

Step 8 is supposed to update to the latest version label v6 but failed.

491587729668_ pic

w000xj commented 4 years ago

Can you reproduce with the steps above? @scrajesh

scrajesh commented 4 years ago

Still not yet, trying the same in iOS. Will keep you posted.

w000xj commented 4 years ago

I use "dependencies": { "electrode-ota-server": "4.6.8", "electrode-ota-server-dao-mariadb": "4.6.8" } on the server.

Digged into manifest.js in electrode-ota-server-model-manifest, the delta function always return files of the latest release package no matter which package the client installed is(I only publish a jsbundle file in each code push release), isn't it ? @scrajesh

scrajesh commented 4 years ago

Followed the steps and still not yet able to reproduce so far. Now i'll try with v4.6.8. Is it possible to track the /updateCheck requests for the steps you've listed above. I wonder if the packageHash param is being sent on each /updateCheck request.

If you're able to track those requests (for all the steps you've listed above), it'd really be great help. Also what is the --targetBinaryVersion parameter you've gave for each release v4/v5/v6 ?

datvong-wm commented 4 years ago

In the steps 2, 4, 6 above, how was the App modified?

w000xj commented 4 years ago

@datvong-wm Just some arbitrary changes on the title.

Let me working on the latest version label v6

  1. Install the apk generated by your demo in two android phone A and B.
  2. Open the app in phone A and phone B press Press for dialog-driven sync on both.(ok).Because there is already a code-push update, the second step above is omitted. Here is the request logged on the server: method: 'get', url: Url { protocol: null, slashes: null, auth: null, host: null, port: null, hostname: null, hash: null, search: '?deploymentKey=RLcQrXaMbyEcmBdAPQxkCUDFmGWfpNMHGKPnHsfl&appVersion=2.0&packageHash=&isCompanion=&label=&clientUniqueId=691adf9e09774521', query: [Object: null prototype] { deploymentKey: 'RLcQrXaMbyEcmBdAPQxkCUDFmGWfpNMHGKPnHsfl', appVersion: '2.0', packageHash: '', isCompanion: '', label: '', clientUniqueId: '691adf9e09774521' }, pathname: '/updateCheck', path: '/updateCheck?deploymentKey=RLcQrXaMbyEcmBdAPQxkCUDFmGWfpNMHGKPnHsfl&appVersion=2.0&packageHash=&isCompanion=&label=&clientUniqueId=691adf9e09774521', href: '/updateCheck?deploymentKey=RLcQrXaMbyEcmBdAPQxkCUDFmGWfpNMHGKPnHsfl&appVersion=2.0&packageHash=&isCompanion=&label=&clientUniqueId=691adf9e09774521' }
  3. Modify App.js, change Hi CodePush hahaha! wow! to Hi to CodePush hahaha! wow!, bundle and release a code-push update containing only a jsbundle file, say label v7. The code-push command is code-push release CodePushDemoAndroid ../build/index.android.bundle 2.0 --deploymentName Staging --description 'b1' --mandatory true
  4. In phone B press Press for dialog-driven sync.(ok) path: '/updateCheck?deploymentKey=RLcQrXaMbyEcmBdAPQxkCUDFmGWfpNMHGKPnHsfl&appVersion=2.0&packageHash=22cc77505bdea594c5bd9c34f945f5299350753ee0272eb583b872e5c197b96c&isCompanion=&label=v6&clientUniqueId=691adf9e09774521' this step will generate a record in table package_diff:
left_package_id right_package_id url
976 478 https://myotaserver/storagev2/3f1abf661c402a967819496c27be663aa93d5c297d789e4bfe19f1144c7858ba

as well as in table package_content:

package_hash content
3f1abf661c402a967819496c27be663aa93d5c297d789e4bfe19f1144c7858ba a pretty large longblob
  1. Modify App.js, change Hi to CodePush hahaha! wow! to Hi CodePush, bundle and release a code-push update containing only a jsbundle file, say label v8. The code-push command is code-push release CodePushDemoAndroid ../build/index.android.bundle 2.0 --deploymentName Staging --description 'b2' --mandatory true

  2. In phone B press Press for dialog-driven sync.(ok) path: '/updateCheck?deploymentKey=RLcQrXaMbyEcmBdAPQxkCUDFmGWfpNMHGKPnHsfl&appVersion=2.0&packageHash=b1bd5841092d3708587a7b74e7794567fd46dafc8ea16252b626b53b37243761&isCompanion=&label=v7&clientUniqueId=691adf9e09774521' like step 4, this step will generate a record in table package_diff:

left_package_id right_package_id url
977 976 https://myotaserver/storagev2/28348ad81f8f82e43837d548edad3977f5fccb3161e84e31bc08c2abe813bbb5

as well as in table package_content:

package_hash content
28348ad81f8f82e43837d548edad3977f5fccb3161e84e31bc08c2abe813bbb5 a pretty large longblob

Now I have phone A updated with label v6 and phone B updated with label v8.

  1. In phone A press Press for dialog-driven sync.(error) path: '/updateCheck?deploymentKey=RLcQrXaMbyEcmBdAPQxkCUDFmGWfpNMHGKPnHsfl&appVersion=2.0&packageHash=22cc77505bdea594c5bd9c34f945f5299350753ee0272eb583b872e5c197b96c&isCompanion=&label=v6&clientUniqueId=175593689cb1c225'

upload error { Error: ER_DUP_ENTRY: Duplicate entry '28348ad81f8f82e43837d548edad3977f5fccb3161e84e31bc08c2abe813bbb5' for key 'PRIMARY' at Query.Sequence._packetToError (/data/ern-ota-server/node_modules/mysql/lib/protocol/sequences/Sequence.js:47:14) . . . at Function.<anonymous> (/data/ern-ota-server/node_modules/electrode-ota-server-dao-mariadb/lib/dao/PackageDAO.js:335:31) at Generator.next (<anonymous>) code: 'ER_DUP_ENTRY', errno: 1062, sqlMessage: 'Duplicate entry \'28348ad81f8f82e43837d548edad3977f5fccb3161e84e31bc08c2abe813bbb5\' for key \'PRIMARY\'', sqlState: '23000', index: 0, sql: 'INSERT INTO package_content\n (package_hash, content)\n VALUES(\'28348ad81f8f82e43837d548edad3977f5fccb3161e84e31bc08c2abe813bbb5\', X\'504b03041...... Step 6 already generated a record in package_content with primary key 28348ad81f8f82e43837d548edad3977f5fccb3161e84e31bc08c2abe813bbb5

Phone B: Install apk --> update to v6 --> update to v7 -->update to v8 Phone A: Install apk --> update to v6 --> error occurs

Phone A is failed to update from label v6 to label v8.

scrajesh commented 4 years ago

@w000xj, finally we were able to reproduce the issue locally and provided a simple fix as of now.

w000xj commented 4 years ago

@w000xj, finally we were able to reproduce the issue locally and provided a simple fix as of now.

Thanks, and where can I find the fix?