private async Task<SyncLogItem> GetSyncLogItem(string uploadAnchor) { var dbLog = client.GetDatabase(DbName); var collectionLog = dbLog.GetCollection<BsonDocument>(SyncLogBucket); var filterLog = Builders<BsonDocument>.Filter.Eq("_id", ObjectId.Parse(uploadAnchor)); var syncLogItem = await collectionLog.Find(filterLog).FirstOrDefaultAsync(); if (syncLogItem != null) { var logItem = new SyncLogItem(); logItem.KeyVersion = new Dictionary<string, string>(); var logItemKV = syncLogItem["KeyVersion"].AsBsonDocument; foreach (var k in logItemKV.Names) { logItem.KeyVersion.Add(k, logItemKV[k].ToString()); } return logItem; } return null; }
public async Task<BatchResponse> Store(string bucketName, BatchSet value) { var db = client.GetDatabase(DbName); var collection = db.GetCollection<BsonDocument>(bucketName); var response = new BatchResponse(); response.BatchItemResponses = new List<BatchItemResponse>(); SyncLogItem syncLogItem = new SyncLogItem(); syncLogItem.KeyVersion = new Dictionary<string, string>(); foreach (var document in value.ChangedDocuments) { var newDoc = Mapper.ToBsonDoc(document); newDoc["_rev"] = this.GenerateNewVersion(); try { var exists = await collection.Find(filter: new BsonDocument { { "_id", document.Key } }).FirstOrDefaultAsync(); if (exists == null && !string.IsNullOrEmpty( document.Version))//somebody else deleted the doc-> conflict { BatchItemResponse respWithError = BuildResponseWithError(document.Key, document.Version, "conflict"); response.ItemsWithErrors++; response.BatchItemResponses.Add(respWithError); continue; } var result = await collection.ReplaceOneAsync(filter: new BsonDocument { { "_id", document.Key }, { "_rev", BsonTypeMapper.MapToBsonValue(document.Version) } }, options: new UpdateOptions { IsUpsert = true }, replacement: newDoc); BatchItemResponse itemResp = new BatchItemResponse { Key = document.Key, Version = newDoc["_rev"].AsString }; response.BatchItemResponses.Add(itemResp); syncLogItem.KeyVersion.Add(itemResp.Key, itemResp.Version); } catch (MongoWriteException ex) { string error = ex.Message; if (ex.Message.Contains("duplicate key"))//conflict { error = "conflict"; } var itemResp = BuildResponseWithError(document.Key, document.Version, error); response.ItemsWithErrors++; response.BatchItemResponses.Add(itemResp); } } foreach (var document in value.DeletedDocuments) { BatchItemResponse itemResp = new BatchItemResponse() { Key = document.Key, Version = document.Version }; var del=await collection.DeleteOneAsync(filter: new BsonDocument { { "_id", document.Key }, { "_rev", BsonTypeMapper.MapToBsonValue(document.Version) } }); if (del.DeletedCount == 0) { var docFromDB= collection.Find(filter: new BsonDocument { { "_id", document.Key } }).FirstOrDefaultAsync(); if (docFromDB != null) { itemResp.Error = "conflict"; itemResp.ErrorDesc = "conflict"; response.ItemsWithErrors++; } } response.BatchItemResponses.Add(itemResp); } //store uploadedAnchor if (syncLogItem.KeyVersion.Count > 0) { syncLogItem.TimeInserted = DateTime.UtcNow; BsonDocument syncLogDoc = new BsonDocument(); syncLogDoc["KeyVersion"] = new BsonDocument(syncLogItem.KeyVersion); syncLogDoc["TimeInserted"] = syncLogItem.TimeInserted; var collectionLog = db.GetCollection<BsonDocument>(SyncLogBucket); await collectionLog.InsertOneAsync(syncLogDoc); response.UploadAnchor = syncLogDoc["_id"].ToString(); } return response; }
private void AddChangedDoc(BatchSet bs, BsonDocument doc, SyncLogItem logItem, Filter query) { if (bs.ChangedDocuments == null) bs.ChangedDocuments = new List<SiaqodbDocument>(); var nestedDoc = doc["o"].AsBsonDocument; if (logItem != null && logItem.KeyVersion != null && logItem.KeyVersion.ContainsKey(nestedDoc["_id"].AsString) && logItem.KeyVersion[nestedDoc["_id"].AsString] == nestedDoc["_rev"].AsString) return; if (OutOfFilter(query, nestedDoc)) return; SiaqodbDocument siaqodbDoc = Mapper.ToSiaqodbDocument(nestedDoc); bs.ChangedDocuments.Add(siaqodbDoc); }
private void AddDeletedDoc(BatchSet bs, BsonDocument doc, SyncLogItem logItem) { if (bs.DeletedDocuments == null) bs.DeletedDocuments = new List<DeletedDocument>(); //check uploaded anchor- means cliet just uploaded this record and we should not return back if (logItem != null && logItem.KeyVersion != null && logItem.KeyVersion.ContainsKey(doc["o"].AsBsonDocument["_id"].AsString)) return; DeletedDocument delDoc = new DeletedDocument(); delDoc.Key = doc["o"].AsBsonDocument["_id"].AsString; bs.DeletedDocuments.Add(delDoc); }
public async Task<BatchResponse> Store(string bucketName, BatchSet batch) { using (var client = new MyCouchClient(DbServerUrl, bucketName)) { var dbExists= await client.Database.HeadAsync(); if (dbExists.IsSuccess) { BulkRequest bulkRequest = new BulkRequest(); DateTime start = DateTime.Now; int size = 0; SiaqodbDocument crObjForUpdateViews = null; if (batch.ChangedDocuments != null) { foreach (SiaqodbDocument obj in batch.ChangedDocuments) { if (obj != null) { if (crObjForUpdateViews == null) crObjForUpdateViews = obj; await CheckTagsViews(client, bucketName, obj.Tags); CouchDBDocument doc = Mapper.ToCouchDBDoc(obj); var serializedObject = client.Serializer.Serialize<CouchDBDocument>(doc); bulkRequest.Include(serializedObject); size += serializedObject.Length; } } } if (batch.DeletedDocuments != null) { foreach (DeletedDocument obj in batch.DeletedDocuments) { if (obj != null) { if (obj.Version != null)//otherwise means is a non-existing object { bulkRequest.Delete(obj.Key, obj.Version); } } } } var response = await client.Documents.BulkAsync(bulkRequest); if (response.IsSuccess) { var cnorResponse = new BatchResponse(); if (response.Rows != null) { cnorResponse.BatchItemResponses = new List<BatchItemResponse>(); SyncLogItem syncLogItem = new SyncLogItem(); syncLogItem.KeyVersion = new Dictionary<string, string>(); foreach (var row in response.Rows) { BatchItemResponse wresp = new BatchItemResponse(); if (!string.IsNullOrEmpty(row.Error)) { cnorResponse.ItemsWithErrors++; } wresp.Error = row.Error; wresp.ErrorDesc = row.Reason; wresp.Key = row.Id; wresp.Version = row.Rev; cnorResponse.BatchItemResponses.Add(wresp); if (string.IsNullOrEmpty(row.Error)) { syncLogItem.KeyVersion.Add(row.Id, row.Rev); } } if (syncLogItem.KeyVersion.Count > 0) { syncLogItem.TimeInserted = DateTime.UtcNow; using (var clientLog = new MyCouchClient(DbServerUrl, SyncLogBucket)) { string serLogItem = Newtonsoft.Json.JsonConvert.SerializeObject(syncLogItem); var logResp = await clientLog.Documents.PostAsync(serLogItem); cnorResponse.UploadAnchor = logResp.Id; } } } if (crObjForUpdateViews != null) { await this.StartRebuildViews(client, crObjForUpdateViews); } return cnorResponse; } else CheckBucketNotFound(bucketName, response); } else if (dbExists.StatusCode == System.Net.HttpStatusCode.NotFound) { throw new BucketNotFoundException(bucketName); } return null; } }
private void AddDeletedDoc(BatchSet changeSet, ChangesResponse<string>.Row row, SyncLogItem logItem) { if (changeSet.DeletedDocuments == null) changeSet.DeletedDocuments = new List<DeletedDocument>(); DeletedDocument delObj = new DeletedDocument() { Key = row.Id, Version = row.Changes[0].Rev }; //check uploaded anchor- means cliet just uploaded this record and we should not return back if (logItem != null && logItem.KeyVersion != null && logItem.KeyVersion.ContainsKey(delObj.Key) && logItem.KeyVersion[delObj.Key] == delObj.Version) return; changeSet.DeletedDocuments.Add(delObj); }
private void AddChangedDoc(BatchSet changeSet, ChangesResponse<string>.Row row, SyncLogItem logItem, Filter query, MyCouch.Serialization.ISerializer serializer) { if (changeSet.ChangedDocuments == null) changeSet.ChangedDocuments = new List<SiaqodbDocument>(); CouchDBDocument co = serializer.Deserialize<CouchDBDocument>(row.IncludedDoc); if (co._id.StartsWith("_design/")) return; //check uploaded anchor- means cliet just uploaded this record and we should not return back if (logItem != null && logItem.KeyVersion != null && logItem.KeyVersion.ContainsKey(co._id) && logItem.KeyVersion[co._id] == co._rev) return; if (OutOfFilter(query, co)) return; changeSet.ChangedDocuments.Add(Mapper.ToSiaqodbDocument(co)); }