Browse code

[mail-api] BM-15118 Fix: simplify the record updates and add a fallback to upsert by uid if everything fails

Thomas Cataldo authored on 13/08/2019 11:23:32
Showing 1 changed files
... ...
@@ -243,6 +243,42 @@ public class DbMailboxRecordsService extends BaseMailboxRecordsService implement
243 243
 		}
244 244
 	}
245 245
 
246
+	private static class UpsertResult {
247
+		final ItemVersion version;
248
+		final boolean update;
249
+
250
+		public UpsertResult(ItemVersion v, boolean b) {
251
+			this.version = v;
252
+			this.update = b;
253
+		}
254
+
255
+		public static UpsertResult create(ItemVersion v) {
256
+			return new UpsertResult(v, false);
257
+		}
258
+
259
+		public static UpsertResult update(ItemVersion v) {
260
+			return new UpsertResult(v, true);
261
+		}
262
+	}
263
+
264
+	private UpsertResult upsertByUid(String uid, MailboxRecord mr) {
265
+		try {
266
+			return UpsertResult.create(storeService.create(uid, uid, mr));
267
+		} catch (ServerFault sf) {
268
+			logger.warn("create failed: {}, trying update of {}", sf.getMessage(), uid);
269
+			return UpsertResult.update(storeService.update(uid, uid, mr));
270
+		}
271
+	}
272
+
273
+	private UpsertResult upsertById(String uid, long id, MailboxRecord mr) {
274
+		try {
275
+			return UpsertResult.create(storeService.createWithId(uid, id, null, uid, mr));
276
+		} catch (ServerFault sf) {
277
+			logger.warn("createById failed: {}, trying updateById of uid: {}, id: {}", sf.getMessage(), uid, id);
278
+			return UpsertResult.update(storeService.update(id, uid, mr));
279
+		}
280
+	}
281
+
246 282
 	@Override
247 283
 	public void updates(List<MailboxRecord> records) {
248 284
 		logger.info("[{}] Update with {} record(s)", mailboxUniqueId, records.size());
... ...
@@ -289,60 +325,54 @@ public class DbMailboxRecordsService extends BaseMailboxRecordsService implement
289 325
 				}
290 326
 
291 327
 				String uid = mr.imapUid + ".";
292
-				ItemVersion version = null;
293
-				boolean update = false;
328
+				UpsertResult upsert = null;
294 329
 
295 330
 				Long expId = GuidExpectedIdCache
296 331
 						.expectedId(IMailReplicaUids.uniqueId(container.uid) + ":" + mr.messageBody);
297 332
 
298 333
 				if (expId != null) {
299
-					version = storeService.createWithId(uid, expId, null, uid, mr);
334
+					upsert = UpsertResult.create(storeService.createWithId(uid, expId, null, uid, mr));
300 335
 					GuidExpectedIdCache.invalidate(IMailReplicaUids.uniqueId(container.uid) + ":" + mr.messageBody);
301 336
 				} else {
302 337
 					ExpectedId knownInternalId = BodyInternalIdCache.expectedRecordId(container.owner, mr.messageBody);
303 338
 					if (knownInternalId == null) {
304
-						try {
305
-							version = storeService.create(uid, uid, mr);
306
-						} catch (ServerFault sf) {
307
-							logger.warn("create failed: {}, trying update of {}", sf.getMessage(), uid);
308
-							version = storeService.update(uid, uid, mr);
309
-							update = true;
310
-						}
339
+						upsert = upsertByUid(uid, mr);
311 340
 					} else {
312 341
 						logger.info("Create directly with the right id {} from replication.", knownInternalId);
313 342
 						if (knownInternalId.updateOfBody == null) {
314
-							try {
315
-								version = storeService.createWithId(uid, knownInternalId.id, null, uid, mr);
316
-							} catch (ServerFault sf) {
317
-								logger.warn("createWithId failed: {}, trying update of {}", sf.getMessage(),
318
-										knownInternalId.id);
319
-								version = storeService.update(knownInternalId.id, uid, mr);
320
-								update = true;
321
-							}
343
+							upsert = upsertById(uid, knownInternalId.id, mr);
322 344
 						} else {
323 345
 							try {
324 346
 								logger.info("Update record {} to point to a different body {}", knownInternalId,
325 347
 										mr.messageBody);
326
-								version = storeService.update(knownInternalId.id, uid, mr);
348
+								upsert = UpsertResult.update(storeService.update(knownInternalId.id, uid, mr));
327 349
 								BodyInternalIdCache.vanishedBody(container.owner,
328
-										knownInternalId.updateOfBody).version = version;
329
-								update = true;
350
+										knownInternalId.updateOfBody).version = upsert.version;
351
+
330 352
 							} catch (ServerFault sf) {
331
-								version = storeService.createWithId(uid, knownInternalId.id, null, uid, mr);
353
+								logger.warn("[{}] Update of {} failed: {}", container.uid, knownInternalId.id,
354
+										sf.getMessage());
355
+								try {
356
+									upsert = UpsertResult
357
+											.create(storeService.createWithId(uid, knownInternalId.id, null, uid, mr));
358
+								} catch (ServerFault refault) {
359
+									logger.warn("byId global failure: {}", refault.getMessage());
360
+									upsert = upsertByUid(uid, mr);
361
+								}
332 362
 							}
333 363
 						}
334 364
 						BodyInternalIdCache.invalidateBody(mr.messageBody);
335 365
 					}
336 366
 				}
337
-				if (!update) {
338
-					crNotifs.add(CreateNotif.of(version.version, version.id, mr.imapUid));
367
+				if (!upsert.update) {
368
+					crNotifs.add(CreateNotif.of(upsert.version.version, upsert.version.id, mr.imapUid));
339 369
 				} else {
340
-					upNotifs.add(UpdateNotif.of(version, mr));
370
+					upNotifs.add(UpdateNotif.of(upsert.version, mr));
341 371
 				}
342 372
 
343 373
 				ItemValue<MailboxRecord> idxAndNotif = ItemValue.create(uid, mr);
344
-				idxAndNotif.internalId = version.id;
345
-				idxAndNotif.version = version.version;
374
+				idxAndNotif.internalId = upsert.version.id;
375
+				idxAndNotif.version = upsert.version.version;
346 376
 
347 377
 				pushToIndex.add(idxAndNotif);
348 378
 				if ("INBOX".equals(recordsLocation.boxName) && recordsLocation.namespace() == Namespace.users