/// <summary> /// This method deletes an entity by its reference. /// </summary> /// <param name="refKey">The reference key, i.e. email etc.</param> /// <param name="refValue">The reference value.</param> /// <param name="settings">The persistence request settings.</param> /// <returns>Returns a response holder that indicates the status of the request and the entity or key and version id where appropriate.</returns> public virtual async Task <RepositoryHolder <K, Tuple <K, string> > > DeleteByRef(string refKey, string refValue, RepositorySettings settings = null) { return(await TransmitInternal(EntityActions.DeleteByRef, new RepositoryHolder <K, Tuple <K, string> > { KeyReference = new Tuple <string, string>(refKey, refValue), Settings = settings }, principal : DefaultPrincipal)); }
/// <summary> /// This method resolves an entity by its reference /// </summary> /// <param name="refKey">The reference key, i.e. email etc.</param> /// <param name="refValue">The reference value.</param> /// <param name="settings">The persistence request settings.</param> /// <returns>Returns a response holder that indicates the status of the request and the entity or key and version id where appropriate.</returns> public virtual async Task <RepositoryHolder <K, Tuple <K, string> > > VersionByRef(string refKey, string refValue, RepositorySettings settings = null) { if ((settings?.UseCache ?? true) && mCacheManager.IsActive) { var result = await mCacheManager.VersionRead(new Tuple <string, string>(refKey, refValue)); if (result.IsSuccess) { return(new RepositoryHolder <K, Tuple <K, string> >(result.Entity.Item1, new Tuple <string, string>(result.Id, result.VersionId), responseCode: 200, entity: result.Entity) { IsCached = true }); } } return(await TransmitInternal(EntityActions.VersionByRef, new RepositoryHolder <K, Tuple <K, string> > { KeyReference = new Tuple <string, string>(refKey, refValue), Settings = settings }, principal : DefaultPrincipal)); }
/// <summary> /// This method reads and entity by the reference key/value pair. /// </summary> /// <param name="refKey">The reference key, i.e. email etc.</param> /// <param name="refValue">The reference value.</param> /// <param name="settings">The persistence request settings.</param> /// <returns>Returns a response holder that indicates the status of the request and the entity or key and version id where appropriate.</returns> public virtual async Task <RepositoryHolder <K, E> > ReadByRef(string refKey, string refValue, RepositorySettings settings = null) { if ((settings?.UseCache ?? true) && mCacheManager.IsActive) { // Do a version read initially to check it is there and get the key (not returned in a read by ref) var resultVersion = await mCacheManager.VersionRead(new Tuple <string, string>(refKey, refValue)); if (resultVersion.IsSuccess) { var resultRead = await mCacheManager.Read(new Tuple <string, string>(refKey, refValue)); if (resultRead.IsSuccess) { return new RepositoryHolder <K, E>(resultVersion.Entity.Item1, new Tuple <string, string>(resultVersion.Id, resultVersion.VersionId), responseCode: 200, entity: resultRead.Entity) { IsCached = true } } ; } } return(await TransmitInternal(EntityActions.ReadByRef, new RepositoryHolder <K, E> { KeyReference = new Tuple <string, string>(refKey, refValue), Settings = settings }, principal : DefaultPrincipal)); }
/// <summary> /// This method deletes an entity by its key. /// </summary> /// <param name="key">The entity key.</param> /// <param name="settings">The persistence request settings.</param> /// <returns>Returns a response holder that indicates the status of the request and the entity or key and version id where appropriate.</returns> public virtual async Task <RepositoryHolder <K, Tuple <K, string> > > Delete(K key, RepositorySettings settings = null) { return(await TransmitInternal(EntityActions.Delete, new RepositoryHolder <K, Tuple <K, string> > { Key = key, Settings = settings }, principal : DefaultPrincipal)); }
/// <summary> /// This method reads an entity based on the key passed. /// </summary> /// <param name="key">The key request.</param> /// <param name="options">These are the repository options which define the request type..</param> /// <returns>This is the holder containing the response and the entity where necessary.</returns> public virtual async Task <RepositoryHolder <SearchRequest, SearchResponse> > Search(SearchRequest key, RepositorySettings options = null) { var uri = mUriMapper.MakeUri(new HttpMethod("Search")); throw new NotImplementedException(); //using (var content = GetContent(entity)) //{ // return await CallClient<K, E>(uri, options, content: content, deserializer: DeserializeEntity, // mapper: (rs, holder) => ExtractHeaders(rs, holder, mKeyMapper)); //} }
/// <summary> /// This method calls the client using HTTP and returns the response along with the entity in the response if supplied. /// </summary> /// <typeparam name="KT">The key type.</typeparam> /// <typeparam name="ET">The entity type.</typeparam> /// <param name="uri">The request uri.</param> /// <param name="options">The repository settings passed from the caller.</param> /// <param name="content">The HttpContent to send to the API.</param> /// <param name="adjust">Any message adjustment.</param> /// <param name="mapper">Any response adjustment before returning to the caller.</param> /// <param name="deserializer">Deserialize the response content into the entity</param> /// <returns></returns> protected virtual async Task <RepositoryHolder <KT, ET> > CallClient <KT, ET>( KeyValuePair <HttpMethod, Uri> uri , RepositorySettings options , HttpContent content = null , Action <HttpRequestMessage> adjust = null , Action <HttpResponseMessage, RepositoryHolder <KT, ET> > mapper = null , Action <HttpResponseMessage, byte[], RepositoryHolder <KT, ET> > deserializer = null) { var response = new RepositoryHolder <KT, ET>(); try { HttpRequestMessage httpRq = Request(uri.Key, uri.Value); RequestHeadersSet(httpRq); RequestHeadersSetTransport(httpRq); RequestHeadersPreferSet(httpRq, options?.Prefer); RequestHeadersAuth(httpRq); adjust?.Invoke(httpRq); if (content != null) { httpRq.Content = content; } var client = new HttpClient(); // Specify request body var httpRs = await client.SendAsync(httpRq); ResponseHeadersAuth(httpRq, httpRs); //OK, set the response content if set if (httpRs.Content != null && httpRs.Content.Headers.ContentLength > 0) { byte[] httpRsContent = await httpRs.Content.ReadAsByteArrayAsync(); if (httpRs.IsSuccessStatusCode) { deserializer?.Invoke(httpRs, httpRsContent, response); } else { // So that we can see error messages such as schema validation fail response.ResponseMessage = Encoding.UTF8.GetString(httpRsContent); } } //Get any outgoing trace headers and set them in to the response. IEnumerable <string> trace; if (httpRs.Headers.TryGetValues(ApimConstants.AzureTraceHeaderLocation, out trace)) { response.Settings.Prefer.Add(ApimConstants.AzureTraceHeaderLocation, trace.First()); } response.ResponseCode = (int)httpRs.StatusCode; mapper?.Invoke(httpRs, response); } catch (Exception ex) { response.ResponseMessage = FormatExceptionChain(ex); response.ResponseCode = 503; } return(response); }
/// <summary> /// This method deletes an entity. /// </summary> /// <param name="key">The entity unique key.</param> /// <param name="options">These are the repository options which define the request type..</param> /// <returns>This is the holder containing the response and the entity where necessary.</returns> public virtual async Task <RepositoryHolder <K, Tuple <K, string> > > Delete(K key, RepositorySettings options = null) { var uri = GetUri(HttpMethod.Delete, key); return(await CallClient <K, Tuple <K, string> >(uri, options , mapper : (rs, holder) => ExtractHeaders(rs, holder))); }
/// <summary> /// This method reads an entity based on the key passed. /// </summary> /// <param name="key">The key request.</param> /// <param name="options">These are the repository options which define the request type..</param> /// <returns>This is the holder containing the response and the entity where necessary.</returns> public virtual async Task <RepositoryHolder <SearchRequest, SearchResponse> > Search(SearchRequest key, RepositorySettings options = null) { throw new NotSupportedException(); }
/// <summary> /// This method logs entities to the event source. This method will try indefinitely /// as we do not want the Event Source to fail. /// </summary> /// <typeparam Name="KT">The key type.</typeparam> /// <param name="actionType"></param> /// <param name="originatorKey"></param> /// <param name="key"></param> /// <param name="entity"></param> /// <param name="settings"></param> protected async virtual Task LogEventSource <KT>(string actionType, string originatorKey, KT key, E entity, RepositorySettings settings) { try { var data = new EventSourceEntry <KT, E> { EntityType = typeof(E).Name, EventType = actionType, Entity = entity, EntityKey = key, EntitySource = settings?.Source, EntitySourceId = settings?.SourceId, EntitySourceName = settings?.SourceName }; if (settings != null) { data.BatchId = settings.BatchId; data.CorrelationId = settings.CorrelationId; data.EntityVersionOld = settings.VersionId; data.EntityVersion = settings.VersionId; } await EventSource.Write(originatorKey, data, sync : true); } catch (Exception ex) { Logger.LogException($"Exception thrown for log to event source on {typeof (E).Name}-{actionType}-{originatorKey}", ex); } }
/// <summary> /// This method reads a reference based on its reference key and value. /// </summary> /// <param name="refKey">The key type.</param> /// <param name="refValue">The key value.</param> /// <param name="options">These are the repository options which define the request type..</param> /// <returns>This is the holder containing the response and the entity where necessary.</returns> public virtual async Task <RepositoryHolder <K, E> > ReadByRef(string refKey, string refValue, RepositorySettings options = null) { var uri = GetUri(HttpMethod.Get, refKey, refValue); return(await CallClient <K, E>(uri, options , deserializer : EntityDeserialize , mapper : (rs, holder) => ExtractHeaders(rs, holder))); }
/// <summary> /// This method resolves an entity by its key. /// </summary> /// <param name="key">The entity key.</param> /// <param name="settings">The persistence request settings.</param> /// <returns>Returns a response holder that indicates the status of the request and the entity or key and version id where appropriate.</returns> public virtual async Task <RepositoryHolder <K, Tuple <K, string> > > Version(K key, RepositorySettings settings = null) { ValidateServiceStarted(); if ((settings?.UseCache ?? true) && mCacheManager.IsActive) { var result = await mCacheManager.VersionRead(key); if (result.IsSuccess) { return(new RepositoryHolder <K, Tuple <K, string> >(result.Entity.Item1, new Tuple <string, string>(result.Id, result.VersionId), responseCode: 200, entity: result.Entity) { IsCached = true }); } } return(await TransmitInternal(EntityActions.Version, new RepositoryHolder <K, Tuple <K, string> > { Key = key, Settings = settings }, principal : DefaultPrincipal)); }
/// <summary> /// This method updates an entity. /// </summary> /// <param name="entity">The entity to update.</param> /// <param name="settings">The persistence settings.</param> /// <returns>Returns a response holder that indicates the status of the request and the entity or key and version id where appropriate.</returns> public virtual async Task <RepositoryHolder <K, E> > Update(E entity, RepositorySettings settings = null) { return(await TransmitInternal(EntityActions.Update, new RepositoryHolder <K, E> { Entity = entity, Settings = settings })); }
/// <summary> /// This method calls the client using HTTP and returns the response along with the entity in the response if supplied. /// </summary> /// <typeparam name="KT">The key type.</typeparam> /// <typeparam name="ET">The entity type.</typeparam> /// <param name="uri">The request uri.</param> /// <param name="options">The repository settings passed from the caller.</param> /// <param name="content">The HttpContent to send to the API.</param> /// <param name="adjust">Any message adjustment.</param> /// <param name="mapper">Any response adjustment before returning to the caller.</param> /// <param name="deserializer">Deserialize the response content into the entity</param> /// <returns></returns> protected virtual async Task <RepositoryHolder <KT, ET> > CallClient <KT, ET>( KeyValuePair <HttpMethod, Uri> uri , RepositorySettings options , HttpContent content = null , Action <HttpRequestMessage> adjust = null , Action <HttpResponseMessage, RepositoryHolder <KT, ET> > mapper = null , Action <HttpResponseMessage, byte[], RepositoryHolder <KT, ET> > deserializer = null) { var rs = new RepositoryHolder <KT, ET>(); try { HttpRequestMessage rq = Request(uri.Key, uri.Value); adjust?.Invoke(rq); if (content != null) { rq.Content = content; } if (options?.Prefer != null && options.Prefer.Count > 0) { rq.Headers.Add("Prefer", options.Prefer.Select((k) => string.Format("{0}={1}", k.Key, k.Value))); } var client = new HttpClient(); // Specify request body var response = await client.SendAsync(rq); if (response.Content != null && response.Content.Headers.ContentLength > 0) { byte[] rsContent = await response.Content.ReadAsByteArrayAsync(); if (response.IsSuccessStatusCode) { deserializer?.Invoke(response, rsContent, rs); } else { // So that we can see error messages such as schema validation fail rs.ResponseMessage = Encoding.UTF8.GetString(rsContent); } } //Get any outgoing trace headers and set them in to the response. IEnumerable <string> trace; if (response.Headers.TryGetValues(ApimConstants.AzureTraceHeaderLocation, out trace)) { rs.Settings.Prefer.Add(ApimConstants.AzureTraceHeaderLocation, trace.First()); } rs.ResponseCode = (int)response.StatusCode; mapper?.Invoke(response, rs); } catch (Exception ex) { rs.ResponseMessage = FormatExceptionChain(ex); rs.ResponseCode = 503; } return(rs); }
/// <summary> /// This method issues a search request. /// </summary> /// <param name="rq">The search request.</param> /// <param name="settings">The persistence request settings.</param> /// <returns>The search response.</returns> public virtual async Task <RepositoryHolder <SearchRequest, SearchResponse> > Search(SearchRequest rq, RepositorySettings settings = null) { //if ((settings?.UseCache ?? true) && mCacheManager.IsActive) //{ // var result = await mCacheManager.VersionRead(new Tuple<string, string>(refKey, refValue)); // if (result.IsSuccess) // { // return new RepositoryHolder<K, Tuple<K, string>>(result.Entity.Item1, new Tuple<string, string>(result.Id, result.VersionId), responseCode: 200, entity: result.Entity) { IsCached = true }; // } //} return(await TransmitInternal(EntityActions.Search, new RepositoryHolder <SearchRequest, SearchResponse> { Key = rq, Settings = settings }, principal : DefaultPrincipal)); }
/// <summary> /// Thi method resolves the entity id and version based on the reference parameters. /// </summary> /// <param name="refKey">The key type.</param> /// <param name="refValue">The key value.</param> /// <param name="options">These are the repository options which define the request type..</param> /// <returns>This is the holder containing the response and the entity where necessary.</returns> public virtual async Task <RepositoryHolder <K, Tuple <K, string> > > VersionByRef(string refKey, string refValue, RepositorySettings options = null) { var uri = GetUri(HttpMethod.Head, refKey, refValue); return(await CallClient <K, Tuple <K, string> >(uri, options , mapper : (rs, holder) => ExtractHeaders(rs, holder))); }
/// <summary> /// This method is used to create an entity in the persistence store. /// </summary> /// <param name="entity">The entity to create.</param> /// <param name="settings">The persistence request settings.</param> /// <returns>Returns a response holder that indicates the status of the request and the entity or key and version id where appropriate.</returns> public virtual async Task <RepositoryHolder <K, E> > Create(E entity, RepositorySettings settings = null) { return(await TransmitInternal(EntityActions.Create, new RepositoryHolder <K, E> { Entity = entity, Settings = settings }, principal : DefaultPrincipal)); }
/// <summary> /// This method resolves the version id of the entity where supported. /// </summary> /// <param name="key">The entity unique key.</param> /// <param name="options">These are the repository options which define the request type..</param> /// <returns>This is the holder containing the response and the entity where necessary.</returns> public virtual async Task <RepositoryHolder <K, Tuple <K, string> > > Version(K key, RepositorySettings options = null) { var uri = mUriMapper.MakeUri(HttpMethod.Head, key); return(await CallClient <K, Tuple <K, string> >(uri, options, mapper : (rs, holder) => ExtractHeaders(rs, holder, mKeyMapper))); }