-
Notifications
You must be signed in to change notification settings - Fork 345
/
Copy pathDaprClient.cs
1490 lines (1384 loc) · 100 KB
/
DaprClient.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
// ------------------------------------------------------------------------
// Copyright 2021 The Dapr Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Reflection;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using Google.Protobuf;
using Grpc.Core;
using Grpc.Core.Interceptors;
using Grpc.Net.Client;
namespace Dapr.Client
{
/// <summary>
/// <para>
/// Defines client methods for interacting with Dapr endpoints.
/// Use <see cref="DaprClientBuilder"/> to create <see cref="DaprClient"/>.
/// </para>
/// <para>
/// Implementations of <see cref="DaprClient" /> implement <see cref="IDisposable" /> because the client
/// accesses network resources. For best performance, create a single long-lived client instance and share
/// it for the lifetime of the application. Avoid creating and disposing a client instance for each operation
/// that the application performs - this can lead to socket exhaustion and other problems.
/// </para>
/// </summary>
public abstract class DaprClient : IDisposable
{
private bool disposed;
/// <summary>
/// Gets the <see cref="JsonSerializerOptions" /> used for JSON serialization operations.
/// </summary>
public abstract JsonSerializerOptions JsonSerializerOptions { get; }
/// <summary>
/// <para>
/// Creates an <see cref="HttpClient" /> that can be used to perform Dapr service
/// invocation using <see cref="HttpRequestMessage" /> objects.
/// </para>
/// <para>
/// The client will read the <see cref="HttpRequestMessage.RequestUri" /> property, and
/// interpret the hostname as the destination <c>app-id</c>. The <see cref="HttpRequestMessage.RequestUri" />
/// property will be replaced with a new URI with the authority section replaced by <paramref name="daprEndpoint" />
/// and the path portion of the URI rewitten to follow the format of a Dapr service invocation request.
/// </para>
/// </summary>
/// <param name="appId">
/// An optional <c>app-id</c>. If specified, the <c>app-id</c> will be configured as the value of
/// <see cref="HttpClient.BaseAddress" /> so that relative URIs can be used. It is mandatory to set this parameter if your app-id contains at least one upper letter.
/// If some requests use absolute URL with an app-id which contains at least one upper letter, it will not work, the workaround is to create one HttpClient for each app-id with the app-ip parameter set.
/// </param>
/// <param name="daprEndpoint">The HTTP endpoint of the Dapr process to use for service invocation calls.</param>
/// <param name="daprApiToken">The token to be added to all request headers to Dapr runtime.</param>
/// <returns>An <see cref="HttpClient" /> that can be used to perform service invocation requests.</returns>
/// <remarks>
/// <para>
/// The <see cref="HttpClient" /> object is intended to be a long-lived and holds access to networking resources.
/// Since the value of <paramref name="daprEndpoint" /> will not change during the lifespan of the application,
/// a single client object can be reused for the life of the application.
/// </para>
/// </remarks>
public static HttpClient CreateInvokeHttpClient(string appId = null, string daprEndpoint = null, string daprApiToken = null)
{
var handler = new InvocationHandler()
{
InnerHandler = new HttpClientHandler(),
DaprApiToken = daprApiToken,
DefaultAppId = appId,
};
if (daprEndpoint is string)
{
// DaprEndpoint performs validation.
handler.DaprEndpoint = daprEndpoint;
}
var httpClient = new HttpClient(handler);
httpClient.DefaultRequestHeaders.UserAgent.Add(UserAgent());
if (appId is string)
{
try
{
httpClient.BaseAddress = new Uri($"http://{appId}");
}
catch (UriFormatException inner)
{
throw new ArgumentException("The appId must be a valid hostname.", nameof(appId), inner);
}
}
return httpClient;
}
/// <summary>
/// <para>
/// Creates an <see cref="CallInvoker"/> that can be used to perform locally defined gRPC calls
/// using the Dapr sidecar as a proxy.
/// </para>
/// <para>
/// The created <see cref="CallInvoker"/> is used to intercept a <see cref="GrpcChannel"/> with an
/// <see cref="InvocationInterceptor"/>. The interceptor inserts the <paramref name="appId"/> and, if present,
/// the <paramref name="daprApiToken"/> into the request's metadata.
/// </para>
/// </summary>
/// <param name="appId">
/// The appId that is targetted by Dapr for gRPC invocations.
/// </param>
/// <param name="daprEndpoint">
/// Optional gRPC endpoint for calling Dapr, defaults to <see cref="DaprDefaults.GetDefaultGrpcEndpoint"/>.
/// </param>
/// <param name="daprApiToken">
/// Optional token to be attached to all requests, defaults to <see cref="DaprDefaults.GetDefaultDaprApiToken"/>.
/// </param>
/// <returns>An <see cref="CallInvoker"/> to be used for proxied gRPC calls through Dapr.</returns>
/// <remarks>
/// <para>
/// As the <paramref name="daprEndpoint"/> will remain constant, a single instance of the
/// <see cref="CallInvoker"/> can be used throughout the lifetime of the application.
/// </para>
/// </remarks>
public static CallInvoker CreateInvocationInvoker(string appId, string daprEndpoint = null, string daprApiToken = null)
{
var channel = GrpcChannel.ForAddress(daprEndpoint ?? DaprDefaults.GetDefaultGrpcEndpoint());
return channel.Intercept(new InvocationInterceptor(appId, daprApiToken ?? DaprDefaults.GetDefaultDaprApiToken()));
}
internal static KeyValuePair<string, string>? GetDaprApiTokenHeader(string apiToken)
{
if (string.IsNullOrWhiteSpace(apiToken))
{
return null;
}
return new KeyValuePair<string, string>("dapr-api-token", apiToken);
}
/// <summary>
/// Publishes an event to the specified topic.
/// </summary>
/// <param name="pubsubName">The name of the pubsub component to use.</param>
/// <param name="topicName">The name of the topic the request should be published to.</param>
/// <param name="data">The data that will be JSON serialized and provided as the event payload.</param>
/// <param name="cancellationToken">A <see cref="CancellationToken" /> that can be used to cancel the operation.</param>
/// <typeparam name="TData">The type of the data that will be JSON serialized and provided as the event payload.</typeparam>
/// <returns>A <see cref="Task" /> that will complete when the operation has completed.</returns>
public abstract Task PublishEventAsync<TData>(
string pubsubName,
string topicName,
TData data,
CancellationToken cancellationToken = default);
/// <summary>
/// Publishes an event to the specified topic.
/// </summary>
/// <param name="pubsubName">The name of the pubsub component to use.</param>
/// <param name="topicName">The name of the topic the request should be published to.</param>
/// <param name="data">The data that will be JSON serialized and provided as the event payload.</param>
/// <param name="metadata">
/// A collection of metadata key-value pairs that will be provided to the pubsub. The valid metadata keys and values
/// are determined by the type of pubsub component used.
/// </param>
/// <param name="cancellationToken">A <see cref="CancellationToken" /> that can be used to cancel the operation.</param>
/// <typeparam name="TData">The type of the data that will be JSON serialized and provided as the event payload.</typeparam>
/// <returns>A <see cref="Task" /> that will complete when the operation has completed.</returns>
public abstract Task PublishEventAsync<TData>(
string pubsubName,
string topicName,
TData data,
Dictionary<string, string> metadata,
CancellationToken cancellationToken = default);
/// <summary>
/// Publishes an event to the specified topic.
/// </summary>
/// <param name="pubsubName">The name of the pubsub component to use.</param>
/// <param name="topicName">The name of the topic the request should be published to.</param>
/// <param name="cancellationToken">A <see cref="CancellationToken" /> that can be used to cancel the operation.</param>
/// <returns>A <see cref="Task" /> that will complete when the operation has completed.</returns>
public abstract Task PublishEventAsync(
string pubsubName,
string topicName,
CancellationToken cancellationToken = default);
/// <summary>
/// Publishes an event to the specified topic.
/// </summary>
/// <param name="pubsubName">The name of the pubsub component to use.</param>
/// <param name="topicName">The name of the topic the request should be published to.</param>
/// <param name="metadata">A collection of metadata key-value pairs that will be provided to the pubsub. The valid metadata keys and values are determined by the type of binding used.</param>
/// <param name="cancellationToken">A <see cref="CancellationToken" /> that can be used to cancel the operation.</param>
/// <returns>A <see cref="Task" /> that will complete when the operation has completed.</returns>
public abstract Task PublishEventAsync(
string pubsubName,
string topicName,
Dictionary<string, string> metadata,
CancellationToken cancellationToken = default);
/// <summary>
/// // Bulk Publishes multiple events to the specified topic.
/// </summary>
/// <param name="pubsubName">The name of the pubsub component to use.</param>
/// <param name="topicName">The name of the topic the request should be published to.</param>
/// <param name="events">The list of events to be published.</param>
/// <param name="metadata">The metadata to be set at the request level for the request.</param>
/// <param name="cancellationToken">A <see cref="CancellationToken" /> that can be used to cancel the operation.</param>
/// <returns>A <see cref="Task" /> that will complete when the operation has completed.</returns>
public abstract Task<BulkPublishResponse<TValue>> BulkPublishEventAsync<TValue>(
string pubsubName,
string topicName,
IReadOnlyList<TValue> events,
Dictionary<string, string> metadata = default,
CancellationToken cancellationToken = default);
/// <summary>
/// Publishes an event to the specified topic.
/// </summary>
/// <param name="pubsubName">The name of the pubsub component to use.</param>
/// <param name="topicName">The name of the topic the request should be published to.</param>
/// <param name="data">The raw byte payload to inlcude in the message.</param>
/// <param name="dataContentType">The content type of the given bytes, defaults to application/json.</param>
/// <param name="metadata">A collection of metadata key-value pairs that will be provided to the pubsub. The valid metadata keys and values are determined by the type of binding used.</param>
/// <param name="cancellationToken">A <see cref="CancellationToken" /> that can be used to cancel the operation.</param>
/// <returns>A <see cref="Task" /> that will complete when the operation has completed.</returns>
public abstract Task PublishByteEventAsync(
string pubsubName,
string topicName,
ReadOnlyMemory<byte> data,
string dataContentType = Constants.ContentTypeApplicationJson,
Dictionary<string, string> metadata = default,
CancellationToken cancellationToken = default);
/// <summary>
/// Invokes an output binding.
/// </summary>
/// <typeparam name="TRequest">The type of the data that will be JSON serialized and provided as the binding payload.</typeparam>
/// <param name="bindingName">The name of the binding to sent the event to.</param>
/// <param name="operation">The type of operation to perform on the binding.</param>
/// <param name="data">The data that will be JSON serialized and provided as the binding payload.</param>
/// <param name="metadata">A collection of metadata key-value pairs that will be provided to the binding. The valid metadata keys and values are determined by the type of binding used.</param>
/// <param name="cancellationToken">A <see cref="CancellationToken" /> that can be used to cancel the operation.</param>
/// <returns>A <see cref="Task" /> that will complete when the operation has completed.</returns>
public abstract Task InvokeBindingAsync<TRequest>(
string bindingName,
string operation,
TRequest data,
IReadOnlyDictionary<string, string> metadata = default,
CancellationToken cancellationToken = default);
/// <summary>
/// Invokes an output binding.
/// </summary>
/// <typeparam name="TRequest">The type of the data that will be JSON serialized and provided as the binding payload.</typeparam>
/// <typeparam name="TResponse">The type of the data that will be JSON deserialized from the binding response.</typeparam>
/// <param name="bindingName">The name of the binding to sent the event to.</param>
/// <param name="operation">The type of operation to perform on the binding.</param>
/// <param name="data">The data that will be JSON serialized and provided as the binding payload.</param>
/// <param name="metadata">A collection of metadata key-value pairs that will be provided to the binding. The valid metadata keys and values are determined by the type of binding used.</param>
/// <param name="cancellationToken">A <see cref="CancellationToken" /> that can be used to cancel the operation.</param>
/// <returns>A <see cref="Task{T}" /> that will complete when the operation has completed.</returns>
public abstract Task<TResponse> InvokeBindingAsync<TRequest, TResponse>(
string bindingName,
string operation,
TRequest data,
IReadOnlyDictionary<string, string> metadata = default,
CancellationToken cancellationToken = default);
/// <summary>
/// Invokes a binding with the provided <paramref name="request" />. This method allows for control of the binding
/// input and output using raw bytes.
/// </summary>
/// <param name="request">The <see cref="BindingRequest" /> to send.</param>
/// <param name="cancellationToken">A <see cref="CancellationToken" /> that can be used to cancel the operation.</param>
/// <returns>A <see cref="Task{T}" /> that will complete when the operation has completed.</returns>
public abstract Task<BindingResponse> InvokeBindingAsync(
BindingRequest request,
CancellationToken cancellationToken = default);
/// <summary>
/// Creates an <see cref="HttpRequestMessage" /> that can be used to perform service invocation for the
/// application identified by <paramref name="appId" /> and invokes the method specified by <paramref name="methodName" />
/// with the <c>POST</c> HTTP method.
/// </summary>
/// <param name="appId">The Dapr application id to invoke the method on.</param>
/// <param name="methodName">The name of the method to invoke.</param>
/// <returns>An <see cref="HttpRequestMessage" /> for use with <c>SendInvokeMethodRequestAsync</c>.</returns>
public HttpRequestMessage CreateInvokeMethodRequest(string appId, string methodName)
{
return CreateInvokeMethodRequest(HttpMethod.Post, appId, methodName);
}
/// <summary>
/// Creates an <see cref="HttpRequestMessage" /> that can be used to perform service invocation for the
/// application identified by <paramref name="appId" /> and invokes the method specified by <paramref name="methodName" />
/// with the HTTP method specified by <paramref name="httpMethod" />.
/// </summary>
/// <param name="httpMethod">The <see cref="HttpMethod" /> to use for the invocation request.</param>
/// <param name="appId">The Dapr application id to invoke the method on.</param>
/// <param name="methodName">The name of the method to invoke.</param>
/// <returns>An <see cref="HttpRequestMessage" /> for use with <c>SendInvokeMethodRequestAsync</c>.</returns>
public abstract HttpRequestMessage CreateInvokeMethodRequest(HttpMethod httpMethod, string appId, string methodName);
/// <summary>
/// Creates an <see cref="HttpRequestMessage" /> that can be used to perform service invocation for the
/// application identified by <paramref name="appId" /> and invokes the method specified by <paramref name="methodName" />
/// with the <c>POST</c> HTTP method and a JSON serialized request body specified by <paramref name="data" />.
/// </summary>
/// <typeparam name="TRequest">The type of the data that will be JSON serialized and provided as the request body.</typeparam>
/// <param name="appId">The Dapr application id to invoke the method on.</param>
/// <param name="methodName">The name of the method to invoke.</param>
/// <param name="data">The data that will be JSON serialized and provided as the request body.</param>
/// <returns>An <see cref="HttpRequestMessage" /> for use with <c>SendInvokeMethodRequestAsync</c>.</returns>
public HttpRequestMessage CreateInvokeMethodRequest<TRequest>(string appId, string methodName, TRequest data)
{
return CreateInvokeMethodRequest<TRequest>(HttpMethod.Post, appId, methodName, data);
}
/// <summary>
/// Creates an <see cref="HttpRequestMessage" /> that can be used to perform service invocation for the
/// application identified by <paramref name="appId" /> and invokes the method specified by <paramref name="methodName" />
/// with the HTTP method specified by <paramref name="httpMethod" /> and a JSON serialized request body specified by
/// <paramref name="data" />.
/// </summary>
/// <typeparam name="TRequest">The type of the data that will be JSON serialized and provided as the request body.</typeparam>
/// <param name="httpMethod">The <see cref="HttpMethod" /> to use for the invocation request.</param>
/// <param name="appId">The Dapr application id to invoke the method on.</param>
/// <param name="methodName">The name of the method to invoke.</param>
/// <param name="data">The data that will be JSON serialized and provided as the request body.</param>
/// <returns>An <see cref="HttpRequestMessage" /> for use with <c>SendInvokeMethodRequestAsync</c>.</returns>
public abstract HttpRequestMessage CreateInvokeMethodRequest<TRequest>(HttpMethod httpMethod, string appId, string methodName, TRequest data);
/// <summary>
/// Perform health-check of Dapr sidecar. Return 'true' if sidecar is healthy. Otherwise 'false'.
/// CheckHealthAsync handle <see cref="HttpRequestException"/> and will return 'false' if error will occur on transport level
/// </summary>
/// <param name="cancellationToken">A <see cref="CancellationToken" /> that can be used to cancel the operation.</param>
/// <returns>A <see cref="Task{T}" /> that will return the value when the operation has completed.</returns>
public abstract Task<bool> CheckHealthAsync(CancellationToken cancellationToken = default);
/// <summary>
/// Perform health-check of Dapr sidecar's outbound APIs. Return 'true' if the sidecar is healthy. Otherwise false. This method should
/// be used over <see cref="CheckHealthAsync(CancellationToken)"/> when the health of Dapr is being checked before it starts. This
/// health endpoint indicates that Dapr has stood up its APIs and is currently waiting on this application to report fully healthy.
/// </summary>
/// <param name="cancellationToken">A <see cref="CancellationToken" /> that can be used to cancel the operation.</param>
/// <returns>A <see cref="Task{T}" /> that will return the value when the operation has completed.</returns>
public abstract Task<bool> CheckOutboundHealthAsync(CancellationToken cancellationToken = default);
/// <summary>
/// Calls <see cref="CheckOutboundHealthAsync(CancellationToken)"/> until the sidecar is reporting as healthy. If the sidecar
/// does not become healthy, an exception will be thrown.
/// </summary>
/// <param name="cancellationToken">A <see cref="CancellationToken" /> that can be used to cancel the operation.</param>
/// <returns>A <see cref="Task" /> that will return when the operation has completed.</returns>
public abstract Task WaitForSidecarAsync(CancellationToken cancellationToken = default);
/// <summary>
/// Send a command to the Dapr Sidecar telling it to shutdown.
/// </summary>
/// <param name="cancellationToken">A <see cref="CancellationToken" /> that can be used to cancel the operation.</param>
/// <returns>A <see cref="Task" /> that will return when the operation has completed.</returns>
public abstract Task ShutdownSidecarAsync(CancellationToken cancellationToken = default);
/// <summary>
/// Calls the sidecar's metadata endpoint which returns information including:
/// <list type="bullet">
/// <item>
/// <description>The sidecar's ID.</description>
/// </item>
/// <item>
/// <description>The registered/active actors if any.</description>
/// </item>
/// <item>
/// <description>Registered components including name, type, version, and information on capabilities if present.</description>
/// </item>
/// <item>
/// <description>Any extended metadata that has been set via <see cref="SetMetadataAsync"/></description>
/// </item>
/// </list>
/// </summary>
/// <param name="cancellationToken">A <see cref="CancellationToken" /> that can be used to cancel the operation.</param>
/// <returns>A <see cref="Task{T}" /> that will return the value when the operation has completed.</returns>
public abstract Task<DaprMetadata> GetMetadataAsync(CancellationToken cancellationToken = default);
/// <summary>
/// Perform service add extended metadata to the Dapr sidecar.
/// </summary>
/// <param name="attributeName">Custom attribute name</param>
/// <param name="attributeValue">Custom attribute value</param>
/// <param name="cancellationToken">A <see cref="CancellationToken" /> that can be used to cancel the operation.</param>
/// <returns>A <see cref="Task" /> that will return the value when the operation has completed.</returns>
public abstract Task SetMetadataAsync(string attributeName, string attributeValue, CancellationToken cancellationToken = default);
/// <summary>
/// Perform service invocation using the request provided by <paramref name="request" />. The response will
/// be returned without performing any validation on the status code.
/// </summary>
/// <param name="request">
/// The <see cref="HttpRequestMessage" /> to send. The request must be a conforming Dapr service invocation request.
/// Use the <c>CreateInvokeMethodRequest</c> to create service invocation requests.
/// </param>
/// <param name="cancellationToken">A <see cref="CancellationToken" /> that can be used to cancel the operation.</param>
/// <returns>A <see cref="Task{T}" /> that will return the value when the operation has completed.</returns>
public abstract Task<HttpResponseMessage> InvokeMethodWithResponseAsync(HttpRequestMessage request, CancellationToken cancellationToken = default);
/// <summary>
/// Perform service invocation using the request provided by <paramref name="request" />. If the response has a non-success
/// status an exception will be thrown.
/// </summary>
/// <param name="request">
/// The <see cref="HttpRequestMessage" /> to send. The request must be a conforming Dapr service invocation request.
/// Use the <c>CreateInvokeMethodRequest</c> to create service invocation requests.
/// </param>
/// <param name="cancellationToken">A <see cref="CancellationToken" /> that can be used to cancel the operation.</param>
/// <returns>A <see cref="Task" /> that will return when the operation has completed.</returns>
public abstract Task InvokeMethodAsync(HttpRequestMessage request, CancellationToken cancellationToken = default);
/// <summary>
/// Perform service invocation using the request provided by <paramref name="request" />. If the response has a success
/// status code the body will be deserialized using JSON to a value of type <typeparamref name="TResponse" />;
/// otherwise an exception will be thrown.
/// </summary>
/// <typeparam name="TResponse">The type of the data that will be JSON deserialized from the response body.</typeparam>
/// <param name="request">
/// The <see cref="HttpRequestMessage" /> to send. The request must be a conforming Dapr service invocation request.
/// Use the <c>CreateInvokeMethodRequest</c> to create service invocation requests.
/// </param>
/// <param name="cancellationToken">A <see cref="CancellationToken" /> that can be used to cancel the operation.</param>
/// <returns>A <see cref="Task{T}" /> that will return the value when the operation has completed.</returns>
public abstract Task<TResponse> InvokeMethodAsync<TResponse>(HttpRequestMessage request, CancellationToken cancellationToken = default);
/// <summary>
/// Perform service invocation for the application identified by <paramref name="appId" /> and invokes the method
/// specified by <paramref name="methodName" /> with the <c>POST</c> HTTP method and an empty request body.
/// If the response has a non-success status code an exception will be thrown.
/// </summary>
/// <param name="appId">The Dapr application id to invoke the method on.</param>
/// <param name="methodName">The name of the method to invoke.</param>
/// <param name="cancellationToken">A <see cref="CancellationToken" /> that can be used to cancel the operation.</param>
/// <returns>A <see cref="Task" /> that will return when the operation has completed.</returns>
public Task InvokeMethodAsync(
string appId,
string methodName,
CancellationToken cancellationToken = default)
{
var request = CreateInvokeMethodRequest(appId, methodName);
return InvokeMethodAsync(request, cancellationToken);
}
/// <summary>
/// Perform service invocation for the application identified by <paramref name="appId" /> and invokes the method
/// specified by <paramref name="methodName" /> with the HTTP method specified by <paramref name="methodName" />
/// and an empty request body. If the response has a non-success status code an exception will be thrown.
/// </summary>
/// <param name="httpMethod">The <see cref="HttpMethod" /> to use for the invocation request.</param>
/// <param name="appId">The Dapr application id to invoke the method on.</param>
/// <param name="methodName">The name of the method to invoke.</param>
/// <param name="cancellationToken">A <see cref="CancellationToken" /> that can be used to cancel the operation.</param>
/// <returns>A <see cref="Task" /> that will return when the operation has completed.</returns>
public Task InvokeMethodAsync(
HttpMethod httpMethod,
string appId,
string methodName,
CancellationToken cancellationToken = default)
{
var request = CreateInvokeMethodRequest(httpMethod, appId, methodName);
return InvokeMethodAsync(request, cancellationToken);
}
/// <summary>
/// Perform service invocation for the application identified by <paramref name="appId" /> and invokes the method
/// specified by <paramref name="methodName" /> with the <c>POST</c> HTTP method
/// and a JSON serialized request body specified by <paramref name="data" />. If the response has a non-success
/// status code an exception will be thrown.
/// </summary>
/// <typeparam name="TRequest">The type of the data that will be JSON serialized and provided as the request body.</typeparam>
/// <param name="appId">The Dapr application id to invoke the method on.</param>
/// <param name="methodName">The name of the method to invoke.</param>
/// <param name="data">The data that will be JSON serialized and provided as the request body.</param>
/// <param name="cancellationToken">A <see cref="CancellationToken" /> that can be used to cancel the operation.</param>
/// <returns>A <see cref="Task" /> that will return when the operation has completed.</returns>
public Task InvokeMethodAsync<TRequest>(
string appId,
string methodName,
TRequest data,
CancellationToken cancellationToken = default)
{
var request = CreateInvokeMethodRequest<TRequest>(appId, methodName, data);
return InvokeMethodAsync(request, cancellationToken);
}
/// <summary>
/// Perform service invocation for the application identified by <paramref name="appId" /> and invokes the method
/// specified by <paramref name="methodName" /> with the HTTP method specified by <paramref name="httpMethod" />
/// and a JSON serialized request body specified by <paramref name="data" />. If the response has a non-success
/// status code an exception will be thrown.
/// </summary>
/// <typeparam name="TRequest">The type of the data that will be JSON serialized and provided as the request body.</typeparam>
/// <param name="httpMethod">The <see cref="HttpMethod" /> to use for the invocation request.</param>
/// <param name="appId">The Dapr application id to invoke the method on.</param>
/// <param name="methodName">The name of the method to invoke.</param>
/// <param name="data">The data that will be JSON serialized and provided as the request body.</param>
/// <param name="cancellationToken">A <see cref="CancellationToken" /> that can be used to cancel the operation.</param>
/// <returns>A <see cref="Task" /> that will return when the operation has completed.</returns>
public Task InvokeMethodAsync<TRequest>(
HttpMethod httpMethod,
string appId,
string methodName,
TRequest data,
CancellationToken cancellationToken = default)
{
var request = CreateInvokeMethodRequest<TRequest>(httpMethod, appId, methodName, data);
return InvokeMethodAsync(request, cancellationToken);
}
/// <summary>
/// Perform service invocation for the application identified by <paramref name="appId" /> and invokes the method
/// specified by <paramref name="methodName" /> with the <c>POST</c> HTTP method
/// and an empty request body. If the response has a success
/// status code the body will be deserialized using JSON to a value of type <typeparamref name="TResponse" />;
/// otherwise an exception will be thrown.
/// </summary>
/// <typeparam name="TResponse">The type of the data that will be JSON deserialized from the response body.</typeparam>
/// <param name="appId">The Dapr application id to invoke the method on.</param>
/// <param name="methodName">The name of the method to invoke.</param>
/// <param name="cancellationToken">A <see cref="CancellationToken" /> that can be used to cancel the operation.</param>
/// <returns>A <see cref="Task{T}" /> that will return the value when the operation has completed.</returns>
public Task<TResponse> InvokeMethodAsync<TResponse>(
string appId,
string methodName,
CancellationToken cancellationToken = default)
{
var request = CreateInvokeMethodRequest(appId, methodName);
return InvokeMethodAsync<TResponse>(request, cancellationToken);
}
/// <summary>
/// Perform service invocation for the application identified by <paramref name="appId" /> and invokes the method
/// specified by <paramref name="methodName" /> with the HTTP method specified by <paramref name="httpMethod" />
/// and an empty request body. If the response has a success
/// status code the body will be deserialized using JSON to a value of type <typeparamref name="TResponse" />;
/// otherwise an exception will be thrown.
/// </summary>
/// <typeparam name="TResponse">The type of the data that will be JSON deserialized from the response body.</typeparam>
/// <param name="httpMethod">The <see cref="HttpMethod" /> to use for the invocation request.</param>
/// <param name="appId">The Dapr application id to invoke the method on.</param>
/// <param name="methodName">The name of the method to invoke.</param>
/// <param name="cancellationToken">A <see cref="CancellationToken" /> that can be used to cancel the operation.</param>
/// <returns>A <see cref="Task{T}" /> that will return the value when the operation has completed.</returns>
public Task<TResponse> InvokeMethodAsync<TResponse>(
HttpMethod httpMethod,
string appId,
string methodName,
CancellationToken cancellationToken = default)
{
var request = CreateInvokeMethodRequest(httpMethod, appId, methodName);
return InvokeMethodAsync<TResponse>(request, cancellationToken);
}
/// <summary>
/// Perform service invocation for the application identified by <paramref name="appId" /> and invokes the method
/// specified by <paramref name="methodName" /> with the <c>POST</c> HTTP method
/// and a JSON serialized request body specified by <paramref name="data" />. If the response has a success
/// status code the body will be deserialized using JSON to a value of type <typeparamref name="TResponse" />;
/// otherwise an exception will be thrown.
/// </summary>
/// <typeparam name="TRequest">The type of the data that will be JSON serialized and provided as the request body.</typeparam>
/// <typeparam name="TResponse">The type of the data that will be JSON deserialized from the response body.</typeparam>
/// <param name="appId">The Dapr application id to invoke the method on.</param>
/// <param name="methodName">The name of the method to invoke.</param>
/// <param name="data">The data that will be JSON serialized and provided as the request body.</param>
/// <param name="cancellationToken">A <see cref="CancellationToken" /> that can be used to cancel the operation.</param>
/// <returns>A <see cref="Task{T}" /> that will return the value when the operation has completed.</returns>
public Task<TResponse> InvokeMethodAsync<TRequest, TResponse>(
string appId,
string methodName,
TRequest data,
CancellationToken cancellationToken = default)
{
var request = CreateInvokeMethodRequest<TRequest>(appId, methodName, data);
return InvokeMethodAsync<TResponse>(request, cancellationToken);
}
/// <summary>
/// Perform service invocation for the application identified by <paramref name="appId" /> and invokes the method
/// specified by <paramref name="methodName" /> with the HTTP method specified by <paramref name="httpMethod" />
/// and a JSON serialized request body specified by <paramref name="data" />. If the response has a success
/// status code the body will be deserialized using JSON to a value of type <typeparamref name="TResponse" />;
/// otherwise an exception will be thrown.
/// </summary>
/// <typeparam name="TRequest">The type of the data that will be JSON serialized and provided as the request body.</typeparam>
/// <typeparam name="TResponse">The type of the data that will be JSON deserialized from the response body.</typeparam>
/// <param name="httpMethod">The <see cref="HttpMethod" /> to use for the invocation request.</param>
/// <param name="appId">The Dapr application id to invoke the method on.</param>
/// <param name="methodName">The name of the method to invoke.</param>
/// <param name="data">The data that will be JSON serialized and provided as the request body.</param>
/// <param name="cancellationToken">A <see cref="CancellationToken" /> that can be used to cancel the operation.</param>
/// <returns>A <see cref="Task{T}" /> that will return the value when the operation has completed.</returns>
public Task<TResponse> InvokeMethodAsync<TRequest, TResponse>(
HttpMethod httpMethod,
string appId,
string methodName,
TRequest data,
CancellationToken cancellationToken = default)
{
var request = CreateInvokeMethodRequest<TRequest>(httpMethod, appId, methodName, data);
return InvokeMethodAsync<TResponse>(request, cancellationToken);
}
/// <summary>
/// Perform service invocation using gRPC semantics for the application identified by <paramref name="appId" /> and invokes the method
/// specified by <paramref name="methodName" /> with an empty request body.
/// If the response has a non-success status code an exception will be thrown.
/// </summary>
/// <param name="appId">The Dapr application id to invoke the method on.</param>
/// <param name="methodName">The name of the method to invoke.</param>
/// <param name="cancellationToken">A <see cref="CancellationToken" /> that can be used to cancel the operation.</param>
/// <returns>A <see cref="Task" /> that will return when the operation has completed.</returns>
public abstract Task InvokeMethodGrpcAsync(
string appId,
string methodName,
CancellationToken cancellationToken = default);
/// <summary>
/// Perform service invocation using gRPC semantics for the application identified by <paramref name="appId" /> and invokes the method
/// specified by <paramref name="methodName" /> with a Protobuf serialized request body specified by <paramref name="data" />.
/// If the response has a non-success status code an exception will be thrown.
/// </summary>
/// <typeparam name="TRequest">The type of the data that will be Protobuf serialized and provided as the request body.</typeparam>
/// <param name="appId">The Dapr application id to invoke the method on.</param>
/// <param name="methodName">The name of the method to invoke.</param>
/// <param name="data">The data that will be Protobuf serialized and provided as the request body.</param>
/// <param name="cancellationToken">A <see cref="CancellationToken" /> that can be used to cancel the operation.</param>
/// <returns>A <see cref="Task" /> that will return when the operation has completed.</returns>
public abstract Task InvokeMethodGrpcAsync<TRequest>(
string appId,
string methodName,
TRequest data,
CancellationToken cancellationToken = default)
where TRequest : IMessage;
/// <summary>
/// Perform service invocation using gRPC semantics for the application identified by <paramref name="appId" /> and invokes the method
/// specified by <paramref name="methodName" /> with an empty request body. If the response has a success
/// status code the body will be deserialized using Protobuf to a value of type <typeparamref name="TResponse" />;
/// otherwise an exception will be thrown.
/// </summary>
/// <typeparam name="TResponse">The type of the data that will be Protobuf deserialized from the response body.</typeparam>
/// <param name="appId">The Dapr application id to invoke the method on.</param>
/// <param name="methodName">The name of the method to invoke.</param>
/// <param name="cancellationToken">A <see cref="CancellationToken" /> that can be used to cancel the operation.</param>
/// <returns>A <see cref="Task{T}" /> that will return the value when the operation has completed.</returns>
public abstract Task<TResponse> InvokeMethodGrpcAsync<TResponse>(
string appId,
string methodName,
CancellationToken cancellationToken = default)
where TResponse : IMessage, new();
/// <summary>
/// Perform service invocation using gRPC semantics for the application identified by <paramref name="appId" /> and invokes the method
/// specified by <paramref name="methodName" /> with a Protobuf serialized request body specified by <paramref name="data" />. If the response has a success
/// status code the body will be deserialized using Protobuf to a value of type <typeparamref name="TResponse" />;
/// otherwise an exception will be thrown.
/// </summary>
/// <typeparam name="TRequest">The type of the data that will be Protobuf serialized and provided as the request body.</typeparam>
/// <typeparam name="TResponse">The type of the data that will be Protobuf deserialized from the response body.</typeparam>
/// <param name="appId">The Dapr application id to invoke the method on.</param>
/// <param name="methodName">The name of the method to invoke.</param>
/// <param name="data">The data that will be Protobuf serialized and provided as the request body.</param>
/// <param name="cancellationToken">A <see cref="CancellationToken" /> that can be used to cancel the operation.</param>
/// <returns>A <see cref="Task{T}" /> that will return the value when the operation has completed.</returns>
public abstract Task<TResponse> InvokeMethodGrpcAsync<TRequest, TResponse>(
string appId,
string methodName,
TRequest data,
CancellationToken cancellationToken = default)
where TRequest : IMessage
where TResponse : IMessage, new();
/// <summary>
/// Gets the current value associated with the <paramref name="key" /> from the Dapr state store.
/// </summary>
/// <param name="storeName">The name of state store to read from.</param>
/// <param name="key">The state key.</param>
/// <param name="consistencyMode">The consistency mode <see cref="ConsistencyMode" />.</param>
/// <param name="metadata">A collection of metadata key-value pairs that will be provided to the state store. The valid metadata keys and values are determined by the type of state store used.</param>
/// <param name="cancellationToken">A <see cref="CancellationToken" /> that can be used to cancel the operation.</param>
/// <typeparam name="TValue">The data type of the value to read.</typeparam>
/// <returns>A <see cref="Task{T}" /> that will return the value when the operation has completed.</returns>
public abstract Task<TValue> GetStateAsync<TValue>(string storeName, string key, ConsistencyMode? consistencyMode = default, IReadOnlyDictionary<string, string> metadata = default, CancellationToken cancellationToken = default);
/// <summary>
/// Gets a list of values associated with the <paramref name="keys" /> from the Dapr state store.
/// </summary>
/// <param name="storeName">The name of state store to read from.</param>
/// <param name="keys">The list of keys to get values for.</param>
/// <param name="parallelism">The number of concurrent get operations the Dapr runtime will issue to the state store. a value equal to or smaller than 0 means max parallelism.</param>
/// <param name="metadata">A collection of metadata key-value pairs that will be provided to the state store. The valid metadata keys and values are determined by the type of state store used.</param>
/// <param name="cancellationToken">A <see cref="CancellationToken" /> that can be used to cancel the operation.</param>
/// <returns>A <see cref="Task{IReadOnlyList}" /> that will return the list of values when the operation has completed.</returns>
public abstract Task<IReadOnlyList<BulkStateItem>> GetBulkStateAsync(string storeName, IReadOnlyList<string> keys, int? parallelism, IReadOnlyDictionary<string, string> metadata = default, CancellationToken cancellationToken = default);
/// <summary>
/// Gets a list of deserialized values associated with the <paramref name="keys" /> from the Dapr state store. This overload should be used
/// if you expect the values of all the retrieved items to match the shape of the indicated <typeparam name="TValue"/>. If you expect that
/// the values may differ in type from one another, do not specify the type parameter and instead use the original <see cref="GetBulkStateAsync"/> method
/// so the serialized string values will be returned instead.
/// </summary>
/// <param name="storeName">The name of state store to read from.</param>
/// <param name="keys">The list of keys to get values for.</param>
/// <param name="parallelism">The number of concurrent get operations the Dapr runtime will issue to the state store. a value equal to or smaller than 0 means max parallelism.</param>
/// <param name="metadata">A collection of metadata key-value pairs that will be provided to the state store. The valid metadata keys and values are determined by the type of state store used.</param>
/// <param name="cancellationToken">A <see cref="CancellationToken" /> that can be used to cancel the operation.</param>
/// <returns>A <see cref="Task{IReadOnlyList}" /> that will return the list of deserialized values when the operation has completed.</returns>
public abstract Task<IReadOnlyList<BulkStateItem<TValue>>> GetBulkStateAsync<TValue>(string storeName, IReadOnlyList<string> keys, int? parallelism, IReadOnlyDictionary<string, string> metadata = default, CancellationToken cancellationToken = default);
/// <summary>
/// Saves a list of <paramref name="items" /> to the Dapr state store.
/// </summary>
/// <param name="storeName">The name of state store.</param>
/// <param name="items">The list of items to save.</param>
/// <param name="cancellationToken">A <see cref="CancellationToken" /> that can be used to cancel the operation.</param>
/// <returns>A <see cref="Task" /> that will complete when the operation has completed.</returns>
public abstract Task SaveBulkStateAsync<TValue>(string storeName, IReadOnlyList<SaveStateItem<TValue>> items, CancellationToken cancellationToken = default);
/// <summary>
/// Deletes a list of <paramref name="items" /> from the Dapr state store.
/// </summary>
/// <param name="storeName">The name of state store to delete from.</param>
/// <param name="items">The list of items to delete</param>
/// <param name="cancellationToken">A <see cref="CancellationToken" /> that can be used to cancel the operation.</param>
/// <returns>A <see cref="Task" /> that will complete when the operation has completed.</returns>
public abstract Task DeleteBulkStateAsync(string storeName, IReadOnlyList<BulkDeleteStateItem> items, CancellationToken cancellationToken = default);
/// <summary>
/// Gets the current value associated with the <paramref name="key" /> from the Dapr state store and an ETag.
/// </summary>
/// <typeparam name="TValue">The data type of the value to read.</typeparam>
/// <param name="storeName">The name of the state store.</param>
/// <param name="key">The state key.</param>
/// <param name="consistencyMode">The consistency mode <see cref="ConsistencyMode" />.</param>
/// <param name="metadata">A collection of metadata key-value pairs that will be provided to the state store. The valid metadata keys and values are determined by the type of state store used.</param>
/// <param name="cancellationToken">A <see cref="CancellationToken" /> that can be used to cancel the operation.</param>
/// <returns>A <see cref="Task{T}" /> that will return the value when the operation has completed. This wraps the read value and an ETag.</returns>
public abstract Task<(TValue value, string etag)> GetStateAndETagAsync<TValue>(string storeName, string key, ConsistencyMode? consistencyMode = default, IReadOnlyDictionary<string, string> metadata = default, CancellationToken cancellationToken = default);
/// <summary>
/// Gets a <see cref="StateEntry{T}" /> for the current value associated with the <paramref name="key" /> from
/// the Dapr state store.
/// </summary>
/// <param name="storeName">The name of the state store.</param>
/// <param name="key">The state key.</param>
/// <param name="consistencyMode">The consistency mode <see cref="ConsistencyMode" />.</param>
/// <param name="metadata">A collection of metadata key-value pairs that will be provided to the state store. The valid metadata keys and values are determined by the type of state store used.</param>
/// <param name="cancellationToken">A <see cref="CancellationToken" /> that can be used to cancel the operation.</param>
/// <typeparam name="TValue">The type of the data that will be JSON deserialized from the state store response.</typeparam>
/// <returns>A <see cref="Task" /> that will return the <see cref="StateEntry{T}" /> when the operation has completed.</returns>
public async Task<StateEntry<TValue>> GetStateEntryAsync<TValue>(string storeName, string key, ConsistencyMode? consistencyMode = default, IReadOnlyDictionary<string, string> metadata = default, CancellationToken cancellationToken = default)
{
ArgumentVerifier.ThrowIfNullOrEmpty(storeName, nameof(storeName));
ArgumentVerifier.ThrowIfNullOrEmpty(key, nameof(key));
var (state, etag) = await this.GetStateAndETagAsync<TValue>(storeName, key, consistencyMode, metadata, cancellationToken);
return new StateEntry<TValue>(this, storeName, key, state, etag);
}
/// <summary>
/// Saves the provided <paramref name="value" /> associated with the provided <paramref name="key" /> to the Dapr state
/// store.
/// </summary>
/// <param name="storeName">The name of the state store.</param>
/// <param name="key">The state key.</param>
/// <param name="value">The data that will be JSON serialized and stored in the state store.</param>
/// <param name="stateOptions">Options for performing save state operation.</param>
/// <param name="metadata">A collection of metadata key-value pairs that will be provided to the state store. The valid metadata keys and values are determined by the type of state store used.</param>
/// <param name="cancellationToken">A <see cref="CancellationToken" /> that can be used to cancel the operation.</param>
/// <typeparam name="TValue">The type of the data that will be JSON serialized and stored in the state store.</typeparam>
/// <returns>A <see cref="Task" /> that will complete when the operation has completed.</returns>
public abstract Task SaveStateAsync<TValue>(
string storeName,
string key,
TValue value,
StateOptions stateOptions = default,
IReadOnlyDictionary<string, string> metadata = default,
CancellationToken cancellationToken = default);
/// <summary>
/// Tries to save the state <paramref name="value" /> associated with the provided <paramref name="key" /> using the
/// <paramref name="etag"/> to the Dapr state. State store implementation will allow the update only if the attached ETag matches with the latest ETag in the state store.
/// store.
/// </summary>
/// <param name="storeName">The name of the state store.</param>
/// <param name="key">The state key.</param>
/// <param name="value">The data that will be JSON serialized and stored in the state store.</param>
/// <param name="etag">An ETag.</param>
/// <param name="stateOptions">Options for performing save state operation.</param>
/// <param name="metadata">A collection of metadata key-value pairs that will be provided to the state store. The valid metadata keys and values are determined by the type of state store used.</param>
/// <param name="cancellationToken">A <see cref="CancellationToken" /> that can be used to cancel the operation.</param>
/// <typeparam name="TValue">The type of the data that will be JSON serialized and stored in the state store.</typeparam>
/// <returns>A <see cref="Task" /> that will complete when the operation has completed. If the wrapped value is true the operation succeeded.</returns>
public abstract Task<bool> TrySaveStateAsync<TValue>(
string storeName,
string key,
TValue value,
string etag,
StateOptions stateOptions = default,
IReadOnlyDictionary<string, string> metadata = default,
CancellationToken cancellationToken = default);
/// <summary>
/// Saves the provided <paramref name="operations" /> to the Dapr state
/// store.
/// </summary>
/// <param name="storeName">The name of the state store.</param>
/// <param name="operations">A list of StateTransactionRequests.</param>
/// <param name="metadata">A collection of metadata key-value pairs that will be provided to the state store. The valid metadata keys and values are determined by the type of state store used.</param>
/// <param name="cancellationToken">A <see cref="CancellationToken" /> that can be used to cancel the operation.</param>
/// <returns>A <see cref="Task" /> that will complete when the operation has completed.</returns>
public abstract Task ExecuteStateTransactionAsync(
string storeName,
IReadOnlyList<StateTransactionRequest> operations,
IReadOnlyDictionary<string, string> metadata = default,
CancellationToken cancellationToken = default);
/// <summary>
/// Deletes the value associated with the provided <paramref name="key" /> in the Dapr state store.
/// </summary>
/// <param name="storeName">The state store name.</param>
/// <param name="key">The state key.</param>
/// <param name="stateOptions">A <see cref="StateOptions" />.</param>
/// <param name="metadata">A collection of metadata key-value pairs that will be provided to the state store. The valid metadata keys and values are determined by the type of state store used.</param>
/// <param name="cancellationToken">A <see cref="CancellationToken" /> that can be used to cancel the operation.</param>
/// <returns>A <see cref="Task" /> that will complete when the operation has completed.</returns>
public abstract Task DeleteStateAsync(
string storeName,
string key,
StateOptions stateOptions = default,
IReadOnlyDictionary<string, string> metadata = default,
CancellationToken cancellationToken = default);
/// <summary>
/// Tries to delete the the state associated with the provided <paramref name="key" /> using the
/// <paramref name="etag"/> from the Dapr state. State store implementation will allow the delete only if the attached ETag matches with the latest ETag in the state store.
/// </summary>
/// <param name="storeName">The state store name.</param>
/// <param name="key">The state key.</param>
/// <param name="etag">An ETag.</param>
/// <param name="stateOptions">A <see cref="StateOptions" />.</param>
/// <param name="metadata">A collection of metadata key-value pairs that will be provided to the state store. The valid metadata keys and values are determined by the type of state store used.</param>
/// <param name="cancellationToken">A <see cref="CancellationToken" /> that can be used to cancel the operation.</param>
/// <returns>A <see cref="Task" /> that will complete when the operation has completed. If the wrapped value is true the operation suceeded.</returns>
public abstract Task<bool> TryDeleteStateAsync(
string storeName,
string key,
string etag,
StateOptions stateOptions = default,
IReadOnlyDictionary<string, string> metadata = default,
CancellationToken cancellationToken = default);
/// <summary>
/// Queries the specified statestore with the given query. The query is a JSON representation of the query as described by the Dapr QueryState API.
/// Note that the underlying statestore must support queries.
/// </summary>
/// <param name="storeName">The name of the statestore.</param>
/// <param name="jsonQuery">A JSON formatted query string.</param>
/// <param name="metadata">Metadata to send to the statestore.</param>
/// <param name="cancellationToken">A <see cref="CancellationToken"/> that can be used to cancel the operation.</param>
/// <typeparam name="TValue">The data type of the value to read.</typeparam>
/// <returns>A <see cref="StateQueryResponse{TValue}"/> that may be paginated, use <see cref="StateQueryResponse{TValue}.Token"/> to continue the query.</returns>
public abstract Task<StateQueryResponse<TValue>> QueryStateAsync<TValue>(
string storeName,
string jsonQuery,
IReadOnlyDictionary<string, string> metadata = default,
CancellationToken cancellationToken = default);
/// <summary>
/// Gets the secret value from the secret store.
/// </summary>
/// <param name="storeName">Secret store name.</param>
/// <param name="key">Key for the secret.</param>
/// <param name="metadata">A collection of metadata key-value pairs that will be provided to the secret store. The valid metadata keys and values are determined by the type of secret store used.</param>
/// <param name="cancellationToken">A <see cref="CancellationToken" /> that can be used to cancel the operation.</param>
/// <returns>A <see cref="Task{T}" /> that will return the value when the operation has completed.</returns>
public abstract Task<Dictionary<string, string>> GetSecretAsync(
string storeName,
string key,
IReadOnlyDictionary<string, string> metadata = default,
CancellationToken cancellationToken = default);
/// <summary>
/// Gets all secret values that the application is allowed to access from the secret store.
/// </summary>
/// <param name="storeName">Secret store name.</param>
/// <param name="metadata">A collection of metadata key-value pairs that will be provided to the secret store. The valid metadata keys and values are determined by the type of secret store used.</param>
/// <param name="cancellationToken">A <see cref="CancellationToken" /> that can be used to cancel the operation.</param>
/// <returns>A <see cref="Task{T}" /> that will return the value when the operation has completed.</returns>
public abstract Task<Dictionary<string, Dictionary<string, string>>> GetBulkSecretAsync(
string storeName,
IReadOnlyDictionary<string, string> metadata = default,
CancellationToken cancellationToken = default);
/// <summary>
/// Get a list of configuration items based on keys from the given statestore.
/// </summary>
/// <param name="storeName">The name of the configuration store to be queried.</param>
/// <param name="keys">An optional list of keys to query for. If provided, the result will only contain those keys. An empty list indicates all keys should be fetched.</param>
/// <param name="metadata">Optional metadata that will be sent to the configuration store being queried.</param>
/// <param name="cancellationToken">A <see cref="CancellationToken" /> that can be used to cancel the operation.</param>
/// <returns>A <see cref="Task"/> containing a <see cref="GetConfigurationResponse"/></returns>
public abstract Task<GetConfigurationResponse> GetConfiguration(
string storeName,
IReadOnlyList<string> keys,
IReadOnlyDictionary<string, string> metadata = default,
CancellationToken cancellationToken = default);
/// <summary>
/// Subscribe to a configuration store for the specified keys and receive an updated value whenever the key is updated in the store.
/// </summary>
/// <param name="storeName">The name of the configuration store to be queried.</param>
/// <param name="keys">An optional list of keys to query for. If provided, the result will only contain those keys. An empty list indicates all keys should be fetched.</param>
/// <param name="metadata">Optional metadata that will be sent to the configuration store being queried.</param>
/// <param name="cancellationToken">A <see cref="CancellationToken" /> that can be used to cancel the operation.</param>
/// <returns>A <see cref="SubscribeConfigurationResponse"/> which contains a reference to the stream.</returns>
public abstract Task<SubscribeConfigurationResponse> SubscribeConfiguration(
string storeName,
IReadOnlyList<string> keys,
IReadOnlyDictionary<string, string> metadata = default,
CancellationToken cancellationToken = default);
/// <summary>
/// Unsubscribe from a configuration store using the specified Id.
/// </summary>
/// <param name="storeName">The name of the configuration store.</param>
/// <param name="id">The Id of the subscription that should no longer be watched.</param>
/// <param name="cancellationToken">A <see cref="CancellationToken" /> that can be used to cancel the operation.</param>
/// <returns></returns>
public abstract Task<UnsubscribeConfigurationResponse> UnsubscribeConfiguration(
string storeName,
string id,
CancellationToken cancellationToken = default);
#region Cryptography
/// <summary>
/// Encrypts an array of bytes using the Dapr Cryptography encryption functionality.
/// </summary>
/// <param name="vaultResourceName">The name of the vault resource used by the operation.</param>
/// <param name="plaintextBytes">The bytes of the plaintext value to encrypt.</param>
/// <param name="keyName">The name of the key to use from the Vault for the encryption operation.</param>
/// <param name="encryptionOptions">Options informing how the encryption operation should be configured.</param>
/// <param name="cancellationToken">A <see cref="CancellationToken"/> that can be used to cancel the operation.</param>
/// <returns>An array of encrypted bytes.</returns>
[Obsolete("The API is currently not stable as it is in the Alpha stage. This attribute will be removed once it is stable.")]
public abstract Task<ReadOnlyMemory<byte>> EncryptAsync(string vaultResourceName,
ReadOnlyMemory<byte> plaintextBytes, string keyName, EncryptionOptions encryptionOptions,
CancellationToken cancellationToken = default);
/// <summary>
/// Encrypts a stream using the Dapr Cryptography encryption functionality.
/// </summary>
/// <param name="vaultResourceName">The name of the vault resource used by the operation.</param>
/// <param name="plaintextStream">The stream containing the bytes of the plaintext value to encrypt.</param>
/// <param name="keyName">The name of the key to use from the Vault for the encryption operation.</param>
/// <param name="encryptionOptions">Options informing how the encryption operation should be configured.</param>
/// <param name="cancellationToken">A <see cref="CancellationToken"/> that can be used to cancel the operation.</param>
/// <returns>An array of encrypted bytes.</returns>
[Obsolete("The API is currently not stable as it is in the Alpha stage. This attribute will be removed once it is stable.")]
public abstract Task<IAsyncEnumerable<ReadOnlyMemory<byte>>> EncryptAsync(string vaultResourceName, Stream plaintextStream, string keyName,
EncryptionOptions encryptionOptions, CancellationToken cancellationToken = default);
/// <summary>
/// Decrypts the specified ciphertext bytes using the Dapr Cryptography encryption functionality.
/// </summary>
/// <param name="vaultResourceName">The name of the vault resource used by the operation.</param>
/// <param name="ciphertextBytes">The bytes of the ciphertext value to decrypt.</param>
/// <param name="keyName">The name of the key to use from the Vault for the decryption operation.</param>
/// <param name="options">Options informing how the decryption operation should be configured.</param>
/// <param name="cancellationToken">A <see cref="CancellationToken"/> that can be used to cancel the operation.</param>
/// <returns>An array of decrypted bytes.</returns>
[Obsolete("The API is currently not stable as it is in the Alpha stage. This attribute will be removed once it is stable.")]
public abstract Task<ReadOnlyMemory<byte>> DecryptAsync(string vaultResourceName, ReadOnlyMemory<byte> ciphertextBytes, string keyName, DecryptionOptions options,
CancellationToken cancellationToken = default);