{"id":18086223,"url":"https://github.com/shibayan/durable-functions-typed-proxy","last_synced_at":"2025-04-12T22:36:34.325Z","repository":{"id":54258091,"uuid":"193051824","full_name":"shibayan/durable-functions-typed-proxy","owner":"shibayan","description":"Type-safe activity helper for Durable Functions","archived":false,"fork":false,"pushed_at":"2022-12-15T15:59:10.000Z","size":64,"stargazers_count":6,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-26T16:45:38.659Z","etag":null,"topics":["azure-functions","durable-functions"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/shibayan.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null},"funding":{"github":"shibayan"}},"created_at":"2019-06-21T07:25:46.000Z","updated_at":"2023-01-10T12:10:41.000Z","dependencies_parsed_at":"2023-01-29T03:30:31.616Z","dependency_job_id":null,"html_url":"https://github.com/shibayan/durable-functions-typed-proxy","commit_stats":null,"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shibayan%2Fdurable-functions-typed-proxy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shibayan%2Fdurable-functions-typed-proxy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shibayan%2Fdurable-functions-typed-proxy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shibayan%2Fdurable-functions-typed-proxy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/shibayan","download_url":"https://codeload.github.com/shibayan/durable-functions-typed-proxy/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248642864,"owners_count":21138352,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["azure-functions","durable-functions"],"created_at":"2024-10-31T16:07:19.574Z","updated_at":"2025-04-12T22:36:34.307Z","avatar_url":"https://github.com/shibayan.png","language":"C#","funding_links":["https://github.com/sponsors/shibayan"],"categories":[],"sub_categories":[],"readme":"# Type-safe activity helper for Durable Functions\n\n[![Build](https://github.com/shibayan/durable-functions-typed-proxy/workflows/Build/badge.svg)](https://github.com/shibayan/durable-functions-typed-proxy/actions/workflows/build.yml)\n[![Downloads](https://badgen.net/nuget/dt/DurableTask.TypedProxy)](https://www.nuget.org/packages/DurableTask.TypedProxy/)\n[![NuGet](https://badgen.net/nuget/v/DurableTask.TypedProxy)](https://www.nuget.org/packages/DurableTask.TypedProxy/)\n[![License](https://badgen.net/github/license/shibayan/durable-functions-typed-proxy)](https://github.com/shibayan/durable-functions-typed-proxy/blob/master/LICENSE)\n\n## Basic usage\n\n### 1. Implement the activity\n\n```csharp\n// Contract for activity\npublic interface IHelloActivity\n{\n    // The return type must be Task or Task \u003cT\u003e\n    Task\u003cstring\u003e SayHello(string name);\n}\n\n// Implementation of activity\npublic class HelloActivity : IHelloActivity\n{\n    [FunctionName(nameof(SayHello))]\n    public Task\u003cstring\u003e SayHello([ActivityTrigger] string name)\n    {\n        return Task.FromResult($\"Hello {name}!\");\n    }\n}\n```\n\n### 2. Create type-safe proxy and called methods\n\n```csharp\npublic class Function1\n{\n    [FunctionName(\"Function1\")]\n    public async Task\u003cList\u003cstring\u003e\u003e RunOrchestrator(\n        [OrchestrationTrigger] DurableOrchestrationContext context)\n    {\n        var outputs = new List\u003cstring\u003e();\n\n        // Create type-safe activity proxy with interface\n        var proxy = context.CreateActivityProxy\u003cIHelloActivity\u003e();\n\n        // Replace \"hello\" with the name of your Durable Activity Function.\n        outputs.Add(await proxy.SayHello(\"Tokyo\"));\n        outputs.Add(await proxy.SayHello(\"Seattle\"));\n        outputs.Add(await proxy.SayHello(\"London\"));\n\n        // returns [\"Hello Tokyo!\", \"Hello Seattle!\", \"Hello London!\"]\n        return outputs;\n    }\n}\n```\n\n## Advanced usage\n\n### Use ILogger\n\n```csharp\npublic class HelloActivity : IHelloActivity\n{\n    public HelloActivity(ILoggerFactory loggerFactory)\n    {\n        // Create logger instance\n        _logger = loggerFactory.CreateLogger\u003cHelloActivity\u003e();\n    }\n    \n    private readonly ILogger _logger;\n\n    [FunctionName(nameof(SayHello))]\n    public Task\u003cstring\u003e SayHello([ActivityTrigger] string name)\n    {\n        _logger.LogInformation($\"Saying hello to {name}.\");\n        return Task.FromResult($\"Hello {name}!\");\n    }\n}\n```\n\n### Retry options\n\n```csharp\npublic interface IHttpGetActivity\n{\n    // Declarative RetryOptions definition\n    [RetryOptions(\"00:00:05\", 10)]\n    Task\u003cstring\u003e HttpGet(string path);\n}\n\npublic class HttpGetActivity : IHttpGetActivity\n{\n    public HttpGetActivity(HttpClient httpClient)\n    {\n        _httpClient = httpClient;\n    }\n\n    private readonly HttpClient _httpClient;\n\n    // In case of failure, retry is performed transparently\n    [FunctionName(nameof(HttpGet))]\n    public Task\u003cstring\u003e HttpGet([ActivityTrigger] string path)\n    {\n        return _httpClient.GetStringAsync(path);\n    }\n}\n```\n\n### Custom retry handler\n\n```csharp\npublic static class RetryStrategy\n{\n    // Implement custom retry handler\n    public static bool HttpError(Exception ex)\n    {\n        return ex.InnerException is HttpRequestException;\n    }\n}\n\npublic interface IHttpGetActivity\n{\n    // Must be setting HandlerType and HandlerMethodName\n    [RetryOptions(\"00:00:05\", 10, HandlerType = typeof(RetryStrategy), HandlerMethodName = nameof(RetryStrategy.HttpError))]\n    Task\u003cstring\u003e HttpGet(string path);\n}\n\npublic class HttpGetActivity : IHttpGetActivity\n{\n    public HttpGetActivity(HttpClient httpClient)\n    {\n        _httpClient = httpClient;\n    }\n\n    private readonly HttpClient _httpClient;\n\n    [FunctionName(nameof(HttpGet))]\n    public Task\u003cstring\u003e HttpGet([ActivityTrigger] string path)\n    {\n        return _httpClient.GetStringAsync(path);\n    }\n}\n```\n\n## Blog\n\n- https://blog.shibayan.jp/entry/20190621/1561114911 (Japanese)\n\n## License\n\nThis project is licensed under the [Apache License 2.0](https://github.com/shibayan/durable-functions-typed-proxy/blob/master/LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshibayan%2Fdurable-functions-typed-proxy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fshibayan%2Fdurable-functions-typed-proxy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshibayan%2Fdurable-functions-typed-proxy/lists"}