/// <summary>
        /// Constructor
        /// </summary>
        /// <param name="bucketName">Name of the bucket that this manager should operate on.</param>
        /// <param name="clientConfig">Configuration object for the database client</param>
        /// <param name="providerRuntime">Runtime reference used to gain access to GrainFactory etc</param>
        public CouchBaseDataManager(string bucketName, ClientConfiguration clientConfig, IProviderRuntime providerRuntime)
        {
            Initialise(bucketName, clientConfig);
            ExpiryManager = new ExpiryManager(providerRuntime);

            Logger = providerRuntime.GetLogger(this.GetType().FullName);
            Logger.Info("{0} - constructor called", this.GetType().FullName);
        }
        /// <summary>
        /// Writes a document representing a grain state object.
        /// </summary>
        /// <param name="collectionName">The type of the grain state object.</param>
        /// <param name="key">The grain id string.</param>
        /// <param name="entityData">The grain state data to be stored.</param>
        /// <param name="eTag"></param>
        /// <returns>Completion promise for this operation.</returns>
        public async Task <string> Write(string collectionName, string key, string entityData, string eTag, string primaryKey)
        {
            var documentId = GetDocumentId(collectionName, key);

            var expiry = await ExpiryManager.GetExpiryAsync(collectionName, entityData, primaryKey);

            var result = string.Empty;

            if (ulong.TryParse(eTag, out var realETag))
            {
                var r = await bucket.UpsertAsync <string>(documentId, entityData, realETag, expiry.Expiry.Expiry);

                if (!r.Success)
                {
                    throw new InconsistentStateException(r.Status.ToString(), eTag, r.Cas.ToString());
                }

                result = r.Cas.ToString();
            }
            else
            {
                var r = await bucket.InsertAsync <string>(documentId, entityData, expiry.Expiry.Expiry);

                //check if key exist and we don't have the CAS
                if (!r.Success && r.Status == Couchbase.IO.ResponseStatus.KeyExists)
                {
                    throw new InconsistentStateException(r.Status.ToString(), eTag, r.Cas.ToString());
                }

                if (!r.Success)
                {
                    throw new Exception(r.Status.ToString());
                }

                result = r.Cas.ToString();
            }

            if (expiry.Expiry.Expiry == TimeSpan.Zero)
            {
                return(result);
            }

            //Notify the grain that there is an expiry value for it so it can ensure it deactivates within the expiry time
            ExpiryManagerEventNotifier.Instance.NotifyGrainOfExpiry(expiry);

            return(result);
        }