/// <summary> /// Txn is used to apply multiple KV operations in a single, atomic transaction. /// </summary> /// <remarks> /// Transactions are defined as a /// list of operations to perform, using the KVOp constants and KVTxnOp structure /// to define operations. If any operation fails, none of the changes are applied /// to the state store. Note that this hides the internal raw transaction interface /// and munges the input and output types into KV-specific ones for ease of use. /// If there are more non-KV operations in the future we may break out a new /// transaction API client, but it will be easy to keep this KV-specific variant /// supported. /// /// Even though this is generally a write operation, we take a QueryOptions input /// and return a QueryMeta output. If the transaction contains only read ops, then /// Consul will fast-path it to a different endpoint internally which supports /// consistency controls, but not blocking. If there are write operations then /// the request will always be routed through raft and any consistency settings /// will be ignored. /// /// // If there is a problem making the transaction request then an error will be /// returned. Otherwise, the ok value will be true if the transaction succeeded /// or false if it was rolled back. The response is a structured return value which /// will have the outcome of the transaction. Its Results member will have entries /// for each operation. Deleted keys will have a nil entry in the, and to save /// space, the Value of each key in the Results will be nil unless the operation /// is a KVGet. If the transaction was rolled back, the Errors member will have /// entries referencing the index of the operation that failed along with an error /// message. /// </remarks> /// <param name="txn">The constructed transaction</param> /// <param name="q">Customized write options</param> /// <param name="ct">A CancellationToken to prematurely end the request</param> /// <returns>The transaction response</returns> public async Task <WriteResult <KVTxnResponse> > Txn(List <KVTxnOp> txn, WriteOptions q, CancellationToken ct = default(CancellationToken)) { var txnOps = new List <TxnOp>(txn.Count); foreach (var kvTxnOp in txn) { txnOps.Add(new TxnOp() { KV = kvTxnOp }); } var req = _client.Put <List <TxnOp>, KVTxnResponse>("/v1/txn", txnOps, q); var txnRes = await req.Execute(ct); var res = new WriteResult <KVTxnResponse>(txnRes, txnRes.Response); res.Response.Success = txnRes.StatusCode == System.Net.HttpStatusCode.OK; return(res); }
/// <summary> /// Execute the POST request to the API /// </summary> /// <param name="ct">Cancellation token for long poll request. If set, OperationCanceledException will be thrown if the request is cancelled before completing</param> /// <returns>The result of the POST, including a deserialised generic type object</returns> public async Task <WriteResult <TOut> > Execute(CancellationToken ct) { Client.CheckDisposed(); var timer = Stopwatch.StartNew(); var result = new WriteResult <TOut>(); HttpContent content = null; var message = new HttpRequestMessage(HttpMethod.Post, BuildConsulUri(Endpoint, Params)); ApplyHeaders(message, Client.Config); message.Content = content; var response = await Client.HttpClient.SendAsync(message, ct).ConfigureAwait(false); result.StatusCode = response.StatusCode; ResponseStream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); if (response.StatusCode != HttpStatusCode.NotFound && !response.IsSuccessStatusCode) { if (ResponseStream == null) { throw new ConsulRequestException(string.Format("Unexpected response, status code {0}", response.StatusCode), response.StatusCode); } using (var sr = new StreamReader(ResponseStream)) { throw new ConsulRequestException(string.Format("Unexpected response, status code {0}: {1}", response.StatusCode, sr.ReadToEnd()), response.StatusCode); } } if (response.IsSuccessStatusCode) { result.Response = Deserialize <TOut>(ResponseStream); } result.RequestTime = timer.Elapsed; return(result); }
public async Task <WriteResult <TOut> > Execute(CancellationToken ct) { Client.CheckDisposed(); timer.Start(); var result = new WriteResult <TOut>(); var response = await Client.HttpClient.DeleteAsync(BuildConsulUri(Endpoint, Params), ct).ConfigureAwait(false); result.StatusCode = response.StatusCode; ResponseStream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); if (response.StatusCode != HttpStatusCode.NotFound && !response.IsSuccessStatusCode) { if (ResponseStream == null) { throw new ConsulRequestException(string.Format("Unexpected response, status code {0}", response.StatusCode)); } using (var sr = new StreamReader(ResponseStream)) { throw new ConsulRequestException(string.Format("Unexpected response, status code {0}: {1}", response.StatusCode, sr.ReadToEnd())); } } if (response.IsSuccessStatusCode) { result.Response = Deserialize <TOut>(ResponseStream); } result.RequestTime = timer.Elapsed; timer.Stop(); return(result); }
public WriteResult(WriteResult other) : base(other) { }