I’m referencing this post: Reuse document ID of deleted document @jens
Setup: Couchbase Lite Android 1.4.1 - SG 1.4 - CB Server 4.5
Here are the reproducible steps:
-
Create document
document.update(new Document.DocumentUpdater() { @Override public boolean update(UnsavedRevision newRevision) { Map<String, Object> itemProperties = newRevision.getUserProperties(); // add properties is omitted newRevision.setUserProperties(itemProperties); return true; } });
Logs in Android Studio:
D/Sync: [sendAsyncRequest()] POST => http://my_ip/my_database/_revs_diff
D/Sync: PusherInternal{http://my_ip/my_database, push, 81e55} [fireTrigger()] => RESUME
D/Sync: firing trigger: RESUME
D/Sync: State transition: IDLE -> RUNNING (via RESUME). this: PusherInternal{http://my_ip/my_database, push, 81e55}
D/Sync: [sendAsyncRequest()] POST => http://my_ip/my_database/_bulk_docs
D/Sync: PusherInternal{http://my_ip/my_database, push, 81e55} [fireTrigger()] => RESUME
D/Sync: firing trigger: RESUME
D/Sync: PusherInternal{http://my_ip/my_database, push, 81e55} [fireTrigger()] => WAITING_FOR_CHANGES
D/Sync: firing trigger: WAITING_FOR_CHANGES
D/Sync: retryReplicationIfError() state=IDLE, error=null, isContinuous()=true, isTransientError()=false
D/Sync: State transition: RUNNING -> IDLE (via WAITING_FOR_CHANGES). this: PusherInternal{http://my_ip/my_database, push, 81e55}
D/Database: Query view null completed in 9 milliseconds
D/Sync: changeTrackerReceivedChange: {seq=342, id=b91a8c08-5e1e-4d1b-a163-9f2b2a7ee0a7::item::e1b849f9631f, changes=[{rev=1-66b5105bb81ffabcfbcdfaccf3350563}]}
D/Sync: PullerInternal{http://my_ip/my_database, pull, 086b8}: adding rev to inbox {b91a8c08-5e1e-4d1b-a163-9f2b2a7ee0a7::item::e1b849f9631f #1-66b5105bb81ffabcfbcdfaccf3350563 @0}
D/Sync: changeTrackerCaughtUp
D/Database: Query view null completed in 7 milliseconds
D/Sync: processInbox called
D/Sync: PullerInternal{http://my_ip/my_database, pull, 086b8} no new remote revisions to fetch. add lastInboxSequence (342) to pendingSequences (com.couchbase.lite.support.SequenceMap@af0c4a0)
D/Database: Query view null completed in 11 milliseconds
D/Sync: PullerInternal{http://my_ip/my_database, pull, 086b8} [fireTrigger()] => WAITING_FOR_CHANGES
D/Sync: firing trigger: WAITING_FOR_CHANGES
D/Sync: retryReplicationIfError() state=IDLE, error=null, isContinuous()=true, isTransientError()=false
D/Sync: PusherInternal{http://my_ip/my_database, push, 81e55}: saveLastSequence() called. lastSequence: 344 remoteCheckpoint: {_id=_local/81e5533350715facec2fa6384adc6b3dde34943a, _rev=0-72, lastSequence=343}
D/Sync: PusherInternal{http://my_ip/my_database, push, 81e55}: start put remote _local document. checkpointID: 81e5533350715facec2fa6384adc6b3dde34943a body: {_rev=0-72, lastSequence=344, _id=_local/81e5533350715facec2fa6384adc6b3dde34943a}
D/Sync: [sendAsyncRequest()] PUT => http://my_ip/my_database/_local/81e5533350715facec2fa6384adc6b3dde34943a
D/Sync: PusherInternal{http://my_ip/my_database, push, 81e55} [fireTrigger()] => RESUME
D/Sync: firing trigger: RESUME
D/Sync: State transition: IDLE -> RUNNING (via RESUME). this: PusherInternal{http://my_ip/my_database, push, 81e55}
D/Sync: com.couchbase.lite.replicator.ReplicationInternal$8@5c4acff: put remote _local document request finished. checkpointID: 81e5533350715facec2fa6384adc6b3dde34943a body: {_rev=0-72, lastSequence=344, _id=_local/81e5533350715facec2fa6384adc6b3dde34943a}
D/Sync: com.couchbase.lite.replicator.ReplicationInternal$8@5c4acff: saved remote checkpoint, updating local checkpoint. RemoteCheckpoint: {_rev=0-73, lastSequence=344, _id=_local/81e5533350715facec2fa6384adc6b3dde34943a}
D/Sync: PusherInternal{http://my_ip/my_database, push, 81e55} [fireTrigger()] => WAITING_FOR_CHANGES
D/Sync: firing trigger: WAITING_FOR_CHANGES
D/Sync: retryReplicationIfError() state=IDLE, error=null, isContinuous()=true, isTransientError()=false
D/Sync: State transition: RUNNING -> IDLE (via WAITING_FOR_CHANGES). this: PusherInternal{http://my_ip/my_database, push, 81e55}
D/Database: Query view null completed in 52 milliseconds
D/Sync: PullerInternal{http://my_ip/my_database, pull, 086b8}: saveLastSequence() called. lastSequence: 342 remoteCheckpoint: {_id=_local/086b8f7ce6e606a9accf45792c5237604b08af71, _rev=0-85, lastSequence=341}
D/Sync: PullerInternal{http://my_ip/my_database, pull, 086b8}: start put remote _local document. checkpointID: 086b8f7ce6e606a9accf45792c5237604b08af71 body: {_rev=0-85, lastSequence=342, _id=_local/086b8f7ce6e606a9accf45792c5237604b08af71}
D/Sync: [sendAsyncRequest()] PUT => http://my_ip/my_database/_local/086b8f7ce6e606a9accf45792c5237604b08af71
D/Sync: PullerInternal{http://my_ip/my_database, pull, 086b8} [fireTrigger()] => RESUME
D/Sync: firing trigger: RESUME
D/Sync: State transition: IDLE -> RUNNING (via RESUME). this: PullerInternal{http://my_ip/my_database, pull, 086b8}
D/Sync: com.couchbase.lite.replicator.ReplicationInternal$8@a411a1b: put remote _local document request finished. checkpointID: 086b8f7ce6e606a9accf45792c5237604b08af71 body: {_rev=0-85, lastSequence=342, _id=_local/086b8f7ce6e606a9accf45792c5237604b08af71}
D/Sync: com.couchbase.lite.replicator.ReplicationInternal$8@a411a1b: saved remote checkpoint, updating local checkpoint. RemoteCheckpoint: {_rev=0-86, lastSequence=342, _id=_local/086b8f7ce6e606a9accf45792c5237604b08af71}
D/Sync: PullerInternal{http://my_ip/my_database, pull, 086b8} [fireTrigger()] => WAITING_FOR_CHANGES
D/Sync: firing trigger: WAITING_FOR_CHANGES
D/Sync: retryReplicationIfError() state=IDLE, error=null, isContinuous()=true, isTransientError()=false
D/Sync: State transition: RUNNING -> IDLE (via WAITING_FOR_CHANGES). this: PullerInternal{http://my_ip/my_database, pull, 086b8}
D/Database: Query view null completed in 46 milliseconds
Document ID is: b91a8c08-5e1e-4d1b-a163-9f2b2a7ee0a7::item::e1b849f9631f
Document in Couchbase Server console:
{
"_sync": {
"rev": "1-66b5105bb81ffabcfbcdfaccf3350563",
"sequence": 342,
"recent_sequences": [
342
],
"history": {
"revs": [
"1-66b5105bb81ffabcfbcdfaccf3350563"
],
"parents": [
-1
],
"channels": [
[
"b91a8c08-5e1e-4d1b-a163-9f2b2a7ee0a7"
]
]
},
"channels": {
"b91a8c08-5e1e-4d1b-a163-9f2b2a7ee0a7": null
},
"time_saved": "2017-12-21T09:17:08.626827144Z"
},
"category": {
"id": "GENERAL",
"name": ""
},
"channels": "b91a8c08-5e1e-4d1b-a163-9f2b2a7ee0a7",
"id": "e1b849f9631f",
"name": "Test1",
"type": "item",
"unit": {
"id": "GENERAL",
"name": ""
}
}
Document deletion:
document.delete();
Logs in Android Studio:
D/Sync: [sendAsyncRequest()] POST => http://my_ip/my_database/_revs_diff
D/Sync: PusherInternal{http://my_ip/my_database, push, 81e55} [fireTrigger()] => RESUME
D/Sync: firing trigger: RESUME
D/Sync: State transition: IDLE -> RUNNING (via RESUME). this: PusherInternal{http://my_ip/my_database, push, 81e55}
D/Sync: [sendAsyncRequest()] POST => http://my_ip/my_database/_bulk_docs
D/Sync: PusherInternal{http://my_ip/my_database, push, 81e55} [fireTrigger()] => RESUME
D/Sync: firing trigger: RESUME
D/OpenGLRenderer: endAllStagingAnimators on 0x989d0600 (MenuPopupWindow$MenuDropDownListView) with handle 0x9b7be6d0
D/Sync: PusherInternal{http://my_ip/my_database, push, 81e55} [fireTrigger()] => WAITING_FOR_CHANGES
D/Sync: firing trigger: WAITING_FOR_CHANGES
D/Sync: retryReplicationIfError() state=IDLE, error=null, isContinuous()=true, isTransientError()=false
D/Sync: State transition: RUNNING -> IDLE (via WAITING_FOR_CHANGES). this: PusherInternal{http://my_ip/my_database, push, 81e55}
D/Database: Query view null completed in 17 milliseconds
D/Sync: changeTrackerReceivedChange: {seq=343, id=b91a8c08-5e1e-4d1b-a163-9f2b2a7ee0a7::item::e1b849f9631f, deleted=true, removed=[b91a8c08-5e1e-4d1b-a163-9f2b2a7ee0a7], changes=[{rev=2-4ac7fab3f183d0124ecf95a8d991206e}]}
D/Sync: PullerInternal{http://my_ip/my_database, pull, 086b8}: adding rev to inbox {b91a8c08-5e1e-4d1b-a163-9f2b2a7ee0a7::item::e1b849f9631f #2-4ac7fab3f183d0124ecf95a8d991206e @0 DEL}
D/Database: Query view null completed in 12 milliseconds
D/Sync: processInbox called
D/Sync: PullerInternal{http://my_ip/my_database, pull, 086b8} no new remote revisions to fetch. add lastInboxSequence (343) to pendingSequences (com.couchbase.lite.support.SequenceMap@af0c4a0)
D/Database: Query view null completed in 15 milliseconds
D/Sync: PusherInternal{http://my_ip/my_database, push, 81e55}: saveLastSequence() called. lastSequence: 345 remoteCheckpoint: {_rev=0-73, lastSequence=344, _id=_local/81e5533350715facec2fa6384adc6b3dde34943a}
D/Sync: PusherInternal{http://my_ip/my_database, push, 81e55}: start put remote _local document. checkpointID: 81e5533350715facec2fa6384adc6b3dde34943a body: {_rev=0-73, lastSequence=345, _id=_local/81e5533350715facec2fa6384adc6b3dde34943a}
D/Sync: [sendAsyncRequest()] PUT => http://my_ip/my_database/_local/81e5533350715facec2fa6384adc6b3dde34943a
D/Sync: PusherInternal{http://my_ip/my_database, push, 81e55} [fireTrigger()] => RESUME
D/Sync: firing trigger: RESUME
D/Sync: State transition: IDLE -> RUNNING (via RESUME). this: PusherInternal{http://my_ip/my_database, push, 81e55}
D/Sync: com.couchbase.lite.replicator.ReplicationInternal$8@71dfa57: put remote _local document request finished. checkpointID: 81e5533350715facec2fa6384adc6b3dde34943a body: {_rev=0-73, lastSequence=345, _id=_local/81e5533350715facec2fa6384adc6b3dde34943a}
D/Sync: com.couchbase.lite.replicator.ReplicationInternal$8@71dfa57: saved remote checkpoint, updating local checkpoint. RemoteCheckpoint: {_rev=0-74, lastSequence=345, _id=_local/81e5533350715facec2fa6384adc6b3dde34943a}
D/Sync: PusherInternal{http://my_ip/my_database, push, 81e55} [fireTrigger()] => WAITING_FOR_CHANGES
D/Sync: firing trigger: WAITING_FOR_CHANGES
D/Sync: retryReplicationIfError() state=IDLE, error=null, isContinuous()=true, isTransientError()=false
D/Sync: State transition: RUNNING -> IDLE (via WAITING_FOR_CHANGES). this: PusherInternal{http://my_ip/my_database, push, 81e55}
D/Database: Query view null completed in 25 milliseconds
D/Sync: PullerInternal{http://my_ip/my_database, pull, 086b8}: saveLastSequence() called. lastSequence: 343 remoteCheckpoint: {_rev=0-86, lastSequence=342, _id=_local/086b8f7ce6e606a9accf45792c5237604b08af71}
D/Sync: PullerInternal{http://my_ip/my_database, pull, 086b8}: start put remote _local document. checkpointID: 086b8f7ce6e606a9accf45792c5237604b08af71 body: {_rev=0-86, lastSequence=343, _id=_local/086b8f7ce6e606a9accf45792c5237604b08af71}
D/Sync: [sendAsyncRequest()] PUT => http://my_ip/my_database/_local/086b8f7ce6e606a9accf45792c5237604b08af71
D/Sync: PullerInternal{http://my_ip/my_database, pull, 086b8} [fireTrigger()] => RESUME
D/Sync: firing trigger: RESUME
D/Sync: State transition: IDLE -> RUNNING (via RESUME). this: PullerInternal{http://my_ip/my_database, pull, 086b8}
D/Sync: com.couchbase.lite.replicator.ReplicationInternal$8@e9de4f3: put remote _local document request finished. checkpointID: 086b8f7ce6e606a9accf45792c5237604b08af71 body: {_rev=0-86, lastSequence=343, _id=_local/086b8f7ce6e606a9accf45792c5237604b08af71}
D/Sync: com.couchbase.lite.replicator.ReplicationInternal$8@e9de4f3: saved remote checkpoint, updating local checkpoint. RemoteCheckpoint: {_rev=0-87, lastSequence=343, _id=_local/086b8f7ce6e606a9accf45792c5237604b08af71}
D/Sync: PullerInternal{http://my_ip/my_database, pull, 086b8} [fireTrigger()] => WAITING_FOR_CHANGES
D/Sync: firing trigger: WAITING_FOR_CHANGES
D/Sync: retryReplicationIfError() state=IDLE, error=null, isContinuous()=true, isTransientError()=false
D/Sync: State transition: RUNNING -> IDLE (via WAITING_FOR_CHANGES). this: PullerInternal{http://my_ip/my_database, pull, 086b8}
D/Database: Query view null completed in 54 milliseconds
Document in Couchbase Server console:
{
"_deleted": true,
"_sync": {
"rev": "2-4ac7fab3f183d0124ecf95a8d991206e",
"flags": 1,
"sequence": 343,
"recent_sequences": [
342,
343
],
"history": {
"revs": [
"2-4ac7fab3f183d0124ecf95a8d991206e",
"1-66b5105bb81ffabcfbcdfaccf3350563"
],
"parents": [
1,
-1
],
"deleted": [
0
],
"channels": [
null,
[
"b91a8c08-5e1e-4d1b-a163-9f2b2a7ee0a7"
]
]
},
"channels": {
"b91a8c08-5e1e-4d1b-a163-9f2b2a7ee0a7": {
"seq": 343,
"rev": "2-4ac7fab3f183d0124ecf95a8d991206e",
"del": true
}
},
"time_saved": "2017-12-21T09:23:16.00999601Z"
}
}
So far a document was created, synced and then deleted. It’s now marked as deleted on the device and on Couchbase Server. Now I enter the same input and hence create a document with the same ID.
Logs in Android Studio:
D/Sync: [sendAsyncRequest()] POST => http://my_ip/my_database/_revs_diff
D/Sync: PusherInternal{http://my_ip/my_database, push, 81e55} [fireTrigger()] => RESUME
D/Sync: firing trigger: RESUME
D/Sync: State transition: IDLE -> RUNNING (via RESUME). this: PusherInternal{http://my_ip/my_database, push, 81e55}
D/Sync: [sendAsyncRequest()] POST => http://my_ip/my_database/_bulk_docs
D/Sync: PusherInternal{http://my_ip/my_database, push, 81e55} [fireTrigger()] => RESUME
D/Sync: firing trigger: RESUME
Warning is here
W/Sync: {error=forbidden, id=b91a8c08-5e1e-4d1b-a163-9f2b2a7ee0a7::item::e1b849f9631f, reason=missing channel access, status=403}: _bulk_docs got an error: com.couchbase.lite.replicator.PusherInternal$6@a2735f8
D/Sync: PusherInternal{http://my_ip/my_database, push, 81e55} [fireTrigger()] => WAITING_FOR_CHANGES
D/Sync: firing trigger: WAITING_FOR_CHANGES
D/Sync: retryReplicationIfError() state=IDLE, error=null, isContinuous()=true, isTransientError()=false
D/Sync: State transition: RUNNING -> IDLE (via WAITING_FOR_CHANGES). this: PusherInternal{http://my_ip/my_database, push, 81e55}
D/Database: Query view null completed in 11 milliseconds
D/Sync: PusherInternal{http://my_ip/my_database, push, 81e55}: saveLastSequence() called. lastSequence: 346 remoteCheckpoint: {_rev=0-74, lastSequence=345, _id=_local/81e5533350715facec2fa6384adc6b3dde34943a}
D/Sync: PusherInternal{http://my_ip/my_database, push, 81e55}: start put remote _local document. checkpointID: 81e5533350715facec2fa6384adc6b3dde34943a body: {_rev=0-74, lastSequence=346, _id=_local/81e5533350715facec2fa6384adc6b3dde34943a}
D/Sync: [sendAsyncRequest()] PUT => http://my_ip/my_database/_local/81e5533350715facec2fa6384adc6b3dde34943a
D/Sync: PusherInternal{http://my_ip/my_database, push, 81e55} [fireTrigger()] => RESUME
D/Sync: firing trigger: RESUME
D/Sync: State transition: IDLE -> RUNNING (via RESUME). this: PusherInternal{http://my_ip/my_database, push, 81e55}
D/Sync: com.couchbase.lite.replicator.ReplicationInternal$8@b586936: put remote _local document request finished. checkpointID: 81e5533350715facec2fa6384adc6b3dde34943a body: {_rev=0-74, lastSequence=346, _id=_local/81e5533350715facec2fa6384adc6b3dde34943a}
D/Sync: com.couchbase.lite.replicator.ReplicationInternal$8@b586936: saved remote checkpoint, updating local checkpoint. RemoteCheckpoint: {_rev=0-75, lastSequence=346, _id=_local/81e5533350715facec2fa6384adc6b3dde34943a}
D/Sync: PusherInternal{http://my_ip/my_database, push, 81e55} [fireTrigger()] => WAITING_FOR_CHANGES
D/Sync: firing trigger: WAITING_FOR_CHANGES
D/Sync: retryReplicationIfError() state=IDLE, error=null, isContinuous()=true, isTransientError()=false
D/Sync: State transition: RUNNING -> IDLE (via WAITING_FOR_CHANGES). this: PusherInternal{http://my_ip/my_database, push, 81e55}
D/Database: Query view null completed in 25 milliseconds
Sync Gateway function:
{
"logFilePath": "/home/sync_gateway/logs/sync_gateway_error.log",
"interface": ":4984",
"adminInterface": ":4985",
"log": [
"CRUD",
"HTTP",
"Access",
"Cache",
"Changes"
],
"databases": {
"my_database": {
"server": "http://localhost:8091",
"bucket": "my_bucket",
"revs_limit": 100,
"allow_empty_password" : true,
"users": {
"GUEST": {
"disabled": true,
"admin_channels": [
"*"
]
}
},
"sync": `function(doc, oldDoc){
if(oldDoc){requireAccess(oldDoc.channels);}
channel (doc.channels) }`
}
}
}
How can I create an entirely new document with the document ID of a deleted document and get it to sync?