Concurrent modification to the same document are not allowed Error Come out When put attachment with same key

35 views
Skip to first unread message

Tim Zhang

unread,
Sep 21, 2014, 3:09:09 AM9/21/14
to rav...@googlegroups.com
The following is my attachment trigger when I update attachment with same key multiple time then the concurrent error occur.

-----------------------------------------------------------------------------------------------------------------------------------------------------------

public class SendCommandForAttachmentPutTrigger : AbstractAttachmentPutTrigger
    {

        private static Logger logger = NLog.LogManager.GetCurrentClassLogger();
        private bool IsNsbrReplication { get; set; }
        private string NsbrSnapshorKeySuffix { get; set; }

        public override VetoResult AllowPut(string key, Stream data, RavenJObject metadata)
        {
            IsNsbrReplication = ReplicationHelper.ContainNsbrReplicationFlag(metadata);
            return base.AllowPut(key, data, metadata);
        }

        public override void OnPut(string key, Stream data, RavenJObject metadata)
        {
            if (ReplicationHelper.ContainNsbrReplicationFlag(metadata))
            {
                ReplicationHelper.RemoveNsbrReplicationFlag(metadata);
            }
            base.OnPut(key, data, metadata);
        }

        public override void AfterPut(string key, Stream data, RavenJObject metadata, Etag etag)
        {
            if (!IsNsbrReplication && !MessageDefinition.IsSystemAttachment(key))
            {
                if (TriggerHelper.UseRobustWayToCatchUnsentMessage(Database))
                {
                    this.NsbrSnapshorKeySuffix = Guid.NewGuid().ToString();
                    StoreFailedSendingMessage(key, data, metadata, etag, this.NsbrSnapshorKeySuffix);
                }
            }
            base.AfterPut(key, data, metadata, etag);
        }

        public override void AfterCommit(string key, Stream data, RavenJObject metadata, Etag etag)
        {
            //if data is bigger than 3.5M, then send it as databus
            //else send it as normal message
            if (IsNsbrReplication)
            {
                return;
            }
            if (MessageDefinition.IsSystemAttachment(key)) // we don't deal with system attachment
                return;
            try
            {
                var replicationSourceInfoJson = ReplicationHelper.CreateReplicationSourceJson(GlobalBus.HostName,
                    Database.Name, etag.ToString());

                byte[] dataByte = ReplicationHelper.GetBytesFromStream(data);
                
                if (MessageDefinition.IsLargeMessage(dataByte))
                {
                    var bigMessage = new PutBigAttachment
                    {
                        Key = key, Etag = etag.ToString(),
                        AttachmentDataBus = dataByte,
                        MetadataJsonString = metadata.ToString(),
                        ReplicationSourceInfoJson = replicationSourceInfoJson
                    };
                    GlobalBus.Bus.Send(bigMessage);
                }
                else
                {
                    var message = new PutAttachment { Key = key, Etag = etag.ToString(),
                        AttachmentData = dataByte,
                        MetadataJsonString = metadata.ToString(),
                        ReplicationSourceInfoJson = replicationSourceInfoJson
                    };
                    GlobalBus.Bus.Send(message);
                }
                if (TriggerHelper.UseRobustWayToCatchUnsentMessage(Database))
                {
                    Database.Delete(RavenConstant.NsbrUnsentAttachmentSnapshotKeyPrefix + this.NsbrSnapshorKeySuffix,null,null);
                    Database.DeleteStatic(RavenConstant.NsbrUnsentAttachmentKeyPrifix + this.NsbrSnapshorKeySuffix, null);
                }
            }
            catch (Exception e)
            {
                if (!TriggerHelper.UseRobustWayToCatchUnsentMessage(Database))
                {
                    var snapshotKeySuffix=Guid.NewGuid().ToString();
                    try
                    {
                        StoreFailedSendingMessage(key, data, metadata, etag, snapshotKeySuffix);
                    }
                    catch (Exception ex)
                    {
                        logger.Fatal("Store PutAttachment Error:({0}-snapshotkeysuffix={1}) {2}", key, snapshotKeySuffix, ex);
                    }
                }
                logger.FatalException("SendCommandForAttachmentPutTrigger key="+key, e);
            }
        }

        private void StoreFailedSendingMessage(string key, Stream data, RavenJObject metadata, Etag etag,string snapshotkeysuffix)
        {
                var snapShotAttachmentKey = RavenConstant.NsbrUnsentAttachmentKeyPrifix+snapshotkeysuffix;
                var ravenJObject =
                    RavenJObject.FromObject(new NsbrUnsentAttachmentSnapshot
                    {
                        Key = key,
                        Etag = etag.ToString(),
                        AttachmentKey = snapShotAttachmentKey,
                        Metadata = metadata.ToString(),
                        ActionType = RavenConstant.NsbrUnsentMessageActionTypePut,
                        SourceDb = Database.Name,
                        SourceHost = GlobalBus.HostName
                    }
                    );
                var snapShotDocMetadata = new RavenJObject{
                    {Constants.RavenEntityName,RavenJToken.FromObject(RavenConstant.NsbrUnsentAttachmentSnapshotKeyPrefix.TrimEnd('/'))}
                };
                Database.Put(RavenConstant.NsbrUnsentAttachmentSnapshotKeyPrefix + snapshotkeysuffix, 
                    null,ravenJObject,
                    snapShotDocMetadata, null);

                var snapShotAttachmentMetadata = new RavenJObject { {"SourceSnapshotEtag",etag.ToString()},
                      {"SourceSnapShotKey",key} 
                };
                data.Position = 0;
                Database.PutStatic(snapShotAttachmentKey, null, data, snapShotAttachmentMetadata);
        }
    }
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Conflict{
  "Url": "/static/zjf/1",
  "ActualETag": "00000000-0000-0000-0000-000000000000",
  "ExpectedETag": "00000000-0000-0000-0000-000000000000",
  "Error": "Concurrent modification to the same document are not allowed"
}
   在 Nsbr.RavenRestClients.RestClientExtensions.ExtensionExecute(RestClient client, IRestRequest request, Boolean useLock) 位置 d:\LTSS\FEIInternal\eLtss\Tools\RavenReplication\Code\Nsbr.RavenRestClients\RestClientExtensions.cs:行号 56
   在 Nsbr.RavenRestClients.RavenHttpApiProxy.PutAttachment(String key, Byte[] bytes, IDictionary`2 metada, String baseUrl, Boolean useLock) 位置 d:\LTSS\FEIInternal\eLtss\Tools\RavenReplication\Code\Nsbr.RavenRestClients\RavenHttpApiProxy.cs:行号 126

Oren Eini (Ayende Rahien)

unread,
Sep 21, 2014, 6:54:29 AM9/21/14
to ravendb
SendCommandForAttachmentPutTrigger is a trigger that has a _single_ instance.
If you are using it concurrently, that can cause issues because you are storing state for the trigger like this.


Hibernating Rhinos Ltd  

Oren Eini l CEO Mobile: + 972-52-548-6969

Office: +972-4-622-7811 l Fax: +972-153-4-622-7811

 


--
You received this message because you are subscribed to the Google Groups "RavenDB - 2nd generation document database" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ravendb+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply all
Reply to author
Forward
0 new messages